
#include "asm/memory.h"
#include "asm/page.h"
#include "dim-sum/mem.h"
#include "dim-sum/smp_lock.h"
#include <dim-sum/types.h>
#include <dim-sum/bug.h>
#include <dim-sum/process.h>
#include <dim-sum/mm.h>
#include <dim-sum/mmu.h>
#include <dim-sum/double_list.h>
#include <dim-sum/mm_types.h>
#include <dim-sum/pagemap.h>
#include <dim-sum/rwsem.h>
#include <dim-sum/beehive.h>
#include <dim-sum/err.h>
#include <dim-sum/errno.h>
#include <dim-sum/fs.h>
#include <dim-sum/syscall.h>
#include <dim-sum/mman.h>
#include <dim-sum/writeback.h>
#include <dim-sum/accurate_counter.h>
#include <asm/uaccess.h>

static struct accurate_counter sys_vma_desc_nr;
static struct accurate_counter sys_mem_desc_nr;

__maybe_unused static char *get_vma_acces_string(struct vma_desc *v)
{
	switch(v->acces & VAC_RWX_MASK) {
		case 0:
			return "none";
		case 1:
			return "read";
		case 2:
			return "write";
		case 3:
			return "read-write";
		case 4:
			return "exec";
		case 5:
			return "exec-read";
		case 6:
			return "exec-write";
		case 7:
			return "exec-read-write";
		default:
			break;
	}
	return "UNKNOWN";
}

__maybe_unused static char *get_vma_type_string(struct vma_desc *v)
{
	if (v->flags & VAF_STACK)
		return "USER STACK";
	if (v->flags & VAF_HEAP)
		return "USER HEAP";
	if (v->flags & VAF_ENV)
		return "USER ENV";
	if (v->acces & VAC_EXEC && v->acces & VAC_READ)
		return "USER TEXT";
	if (v->acces & VAC_WRITE || v->acces & VAC_READ)
		return "USER DATA";	
	return "UNKNOWN";
}

struct vma_desc *alloced_vma_desc(void)
{
	struct vma_desc *v;
	v = (struct vma_desc *)
		kzalloc(sizeof(struct vma_desc), PAF_KERNEL);

	if (!v)
		return NULL;
	accurate_inc(&sys_vma_desc_nr);
	vma_desc_init(v);
	return v;
}

void free_vma_desc(struct vma_desc *v)
{
	BUG_ON(!v);
	kfree((void *)v);
	accurate_dec(&sys_vma_desc_nr);
	return;
}

static struct mem_desc *alloced_mem_desc(void)
{
	struct mem_desc *m;
	m = (struct mem_desc *)
		kzalloc(sizeof(struct mem_desc), PAF_KERNEL);

	if (!m)
		return NULL;

	accurate_inc(&sys_mem_desc_nr);
	mem_desc_init(m);
	return m;
}

static void free_mem_desc(struct mem_desc *m)
{
	BUG_ON(!m);
	m->status = MMS_EXIT;
	kfree((void *)m);

	accurate_dec(&sys_mem_desc_nr);
	return;
}

long mem_desc_get(struct mem_desc *m)
{
	BUG_ON(!m);
	return accurate_inc(&m->count);
}

long mem_desc_put(struct mem_desc *m)
{
	BUG_ON(!m);
	return accurate_dec(&m->count);
}

/**
 * 创建进程的内存描述符
 */
int create_mem_desc(struct process_desc *proc)
{
	struct mem_desc *m;
	if (!proc)
		return -EINVAL;
	if (proc->mem)
		return -ENOTEMPTY;
	/**
	 * 分配内存描述符并初始化
	 */
	m = alloced_mem_desc();
	if (!m)
		return -ENOMEM;
	/**
	 * 增加内存描述符计数器
	 */
	mem_desc_get(m);
	m->at_proc = proc;
	m->vm_start = USER_VA_START;
	m->vm_end = USER_VA_END;
	m->vm_size = m->vm_end - m->vm_start;
	/**
	 * 设置 aio 属性
	 */
	smp_lock_init(&m->ioctx_lock);
	hash_list_init_bucket(&m->ioctx_list);
	/**
	 * 将内存描述符地址原子写入进程描述符的相关字段中
	 */
	__set_process_mem(proc, m);
	return 0;
}

static void set_vma_cache(struct mem_desc *m, struct vma_desc *v)
{
	BUG_ON(!m);
	m->vma_cache = v;
	return;
}

static inline int uadd_is_ok(virt_addr_t x, virt_addr_t y)
{
	virt_addr_t s = x + y;
	if (s >= x)
		return 1;
	else
		return 0;
}

/**
 * 获取描述文件的数据结构,基于文件句柄
 */
static void *get_file_on_fd(int fd)
{
	if (fd < 0)
		return NULL;
	/**
	 * 应该获取描述文件的数据结构
	 */
	return (void *)file_find(fd);
}


/**
 * 插入虚拟地址区间
 */
void *insert_vma_desc(struct mem_desc *m, struct vma_desc **out,
					struct vma_desc *vpos, struct vma_desc *v, int ins_state)
{
	if (ins_state == FVSTATE_EMPTY ||
		ins_state == FVSTATE_NULL_EMPTY) {
		list_insert_front(&v->list, &m->vma_list);
		*out = v;
		return (void *)(v->start);
	}

	if (!vpos) {
		*out = NULL;
		return NULL;
	}

	if (ins_state == FVSTATE_ON_PREV ||
		ins_state == FVSTATE_NULL_ON_PREV) {
		list_insert_behind(&v->list, &vpos->list);
		*out = v;
		return (void *)(v->start);
	}
	if (ins_state == FVSTATE_ON_NEXT ||
		ins_state == FVSTATE_NULL_ON_NEXT) {
		list_insert_front(&v->list, &vpos->list);
		*out = v;
		return (void *)(v->start);
	}
	*out = NULL;
	return NULL;
}

/**
 * 插入新虚拟地址区间的数据
 */
static void *set_new_vma_desc(struct mem_desc *m, struct vma_desc *v,
					struct vma_desc *vpos, int ins_state,
					virt_addr_t start, virt_addr_t end,
					u64 access, u64 flags, void *file, off_t offset)
{
	virt_size_t size; 
	int error;
	
    BUG_ON(!v || !m);
	v->at_mem = m;
	v->acces = access;
	v->flags = flags;
	v->offset = offset;
	size = end - start + 1;

	if (file) {
		error = -EINVAL;
		v->file = file;
		hold_file(v->file);
		//TODO：这里后面需要修改，等到实现了默认的generic_file_mmap之后
		if (v->file->file_ops && v->file->file_ops->mmap && v->file->file_ops->mmap != &generic_file_mmap) {
			error = v->file->file_ops->mmap(v->file, (struct vm_area_struct*)v);
			if (error)
				return NULL;
			v->ops->open(v);
		}
	}
	
	if (ins_state == FVSTATE_EMPTY) {
		v->start = start;
		v->end = v->start + size - 1;
		return (void *)(v->start);
	}
	if (ins_state == FVSTATE_NULL_EMPTY) {
		v->start = USER_ALLOC_START;
		v->end = v->start + size - 1;
		return (void *)(v->start);
	}
	if (ins_state == FVSTATE_ON_PREV) {
		v->start = start;
		v->end = v->start + size - 1;
		return (void *)(v->start);
	}
	if (ins_state == FVSTATE_ON_NEXT) {
		v->start = start;
		v->end = v->start + size - 1;
		return (void *)(v->start);
	}

	if (ins_state == FVSTATE_NULL_ON_PREV) {
		BUG_ON(!vpos);
		v->start = vpos->start - (size);
		v->end = v->start + size - 1;
		return (void *)(v->start);
	}
	if (ins_state == FVSTATE_NULL_ON_NEXT) {
		BUG_ON(!vpos);
		v->start = vpos->end + 1;
		v->end = v->start + size - 1;
		return (void *)(v->start);
	}
	return NULL;
}

/**
 * 扩展虚拟地址区间
 */
static void *exten_vma_desc(struct vma_desc *v, struct vma_desc **out,
					int ins_state, virt_addr_t start, virt_addr_t end)
{
	void *ret = NULL;
	virt_size_t size = end - start + 1;
	if (!v) {
		*out = NULL;
		return NULL;
	}
	if (ins_state == FVSTATE_DN_EXT) {
		v->start = start;
		ret = (void *)(v->start);
		*out = v;
		return ret;
	}
	if (ins_state == FVSTATE_UP_EXT) {
		v->end = end;
		ret = (void *)start;
		*out = v;
		return ret;
	}

	if (ins_state == FVSTATE_NULL_DN_EXT) {
		v->start = v->start - size;
		ret = (void *)(v->start);
		*out = v;
		return ret;
	}
	if (ins_state == FVSTATE_NULL_UP_EXT) {
		ret = (void *)(v->end + 1);
		v->end = v->end + 1 + end;
		*out = v;
		return ret;
	}
	*out = NULL;
	return NULL;
}

/**
 * 判断vma是否能向下向上扩展
 */
static int vma_is_extn(struct mem_desc *m, struct vma_desc *v,
					int ins_state, virt_addr_t start, virt_addr_t end,
					u64 access, u64 flags,
					void *file, off_t offset)
{
	struct vma_desc *p, *n;
	virt_addr_t dnstart;
	virt_addr_t dnend;
	virt_addr_t upstart;
	virt_addr_t upend;
	virt_size_t size;
	/**
	 * 如果是文件映射暂时不对现有vma扩展
	 */
	if (!v || file)
		return ins_state;
	if (ins_state == FVSTATE_EMPTY || ins_state == FVSTATE_NULL_EMPTY)
		return ins_state;

	p = vma_prev(v, m);
	n = vma_next(v, m);

	if (v->acces == access && v->flags == flags) {
		if (ins_state == FVSTATE_ON_PREV) {
			if ((end + 1) == v->start) {
				if (p) {
					if (start > p->end)
						return FVSTATE_DN_EXT;
				} else if (p == NULL) {
					if (start >= USER_ALLOC_START)
						return FVSTATE_DN_EXT;
				}
			}
		}
		if (ins_state == FVSTATE_ON_NEXT) {
			if ((start - 1) == v->end) {
				if (n) {
					if (end < n->start)
						return FVSTATE_UP_EXT;
				} else if (n == NULL) {
					if (end < USER_ALLOC_END)
						return FVSTATE_UP_EXT;
				}
			}
		}
		if (ins_state == FVSTATE_NULL_ON_PREV) {
			BUG_ON(start >= end);
			size = end - start + 1;
			dnstart = v->start - size;
			dnend = dnstart + size - 1;

			if (p) {
				if (dnstart > p->end && dnend < v->start)
					return FVSTATE_NULL_DN_EXT;
			} else if (p == NULL) {
				if (dnstart >= USER_ALLOC_START && dnend < v->start)
					return FVSTATE_NULL_DN_EXT;
			}
		}
		if (ins_state == FVSTATE_NULL_ON_NEXT) {
			BUG_ON(start >= end);
			size = end - start + 1;
			upstart = v->end + 1;
			upend = upstart + size - 1;

			if (n) {
				if (upstart > v->end && upend < n->start)
					return FVSTATE_NULL_UP_EXT;
			} else if (n == NULL) {
				if (upstart > v->end && upend < USER_ALLOC_END)
					return FVSTATE_NULL_UP_EXT;
			}
		}
	}
	return ins_state;
}

static int vma_where_onlyone(struct vma_desc *v, virt_addr_t start,
				virt_addr_t end)
{
	virt_addr_t dnstart;
	virt_addr_t dnend;
	virt_addr_t upstart;
	virt_addr_t upend;
	if (start) {
		if (end < v->start && start >= USER_ALLOC_START)
			return FVSTATE_ON_PREV;
		if (start > v->end && end < USER_ALLOC_END)
			return FVSTATE_ON_NEXT;
	} else if (start == 0) {
		if (v->end < USER_ALLOC_END) {
			upstart = v->end + 1;
			if (uadd_is_ok(upstart, end)) {
				upend = upstart + end;
				if (upend < USER_ALLOC_END && upstart > v->end)
					return FVSTATE_NULL_ON_NEXT;
			}
		}

		if (v->start >= (end - start + 1)) {
			dnstart = v->start - (end - start + 1);
			if (uadd_is_ok(dnstart, end)) {
				dnend = dnstart + end;
				if (dnstart >= USER_ALLOC_START && dnend < v->start)
					return FVSTATE_NULL_ON_PREV;
			}
		}
	}

	return FVSTATE_ERROR;
}

static int vma_where_prev(struct vma_desc *p, struct vma_desc *v,
				virt_addr_t start, virt_addr_t end)
{
	virt_addr_t dnstart;
	virt_addr_t dnend;
	virt_addr_t upstart;
	virt_addr_t upend;
	if (start) {
		if (p->end < start && end < v->start)
			return FVSTATE_ON_PREV;
		if (start > v->end && end < USER_ALLOC_END)
			return FVSTATE_ON_NEXT;
	} else if (start == 0) {
		if (v->end < USER_ALLOC_END) {
			upstart = v->end + 1;
			if (uadd_is_ok(upstart, end)) {
				upend = upstart + end;
				if (upend < USER_ALLOC_END && upstart > v->end)
					return FVSTATE_NULL_ON_NEXT;
			}
		}

		if (v->start >= (end - start + 1)) {
			dnstart = v->start - (end - start + 1);
			if (uadd_is_ok(dnstart, end)) {
				dnend = dnstart + end;
				if (dnstart > p->end && dnend < v->start)
					return FVSTATE_NULL_ON_PREV;
			}
		}
	}

	return FVSTATE_ERROR;
}

static int vma_where_next(struct vma_desc *v, struct vma_desc *n,
				virt_addr_t start, virt_addr_t end)
{
	virt_addr_t dnstart;
	virt_addr_t dnend;
	virt_addr_t upstart;
	virt_addr_t upend;
	if (start) {
		if (end < v->start && start >= USER_ALLOC_START)
			return FVSTATE_ON_PREV;
		if (start > v->end && end < n->start)
			return FVSTATE_ON_NEXT;
	} else if (start == 0) {
		if (v->end < USER_ALLOC_END) {
			upstart = v->end + 1;
			if (uadd_is_ok(upstart, end)) {
				upend = upstart + end;
				if ((upend) < n->start && upstart > v->end)
					return FVSTATE_NULL_ON_NEXT;
			}
		}

		if (v->start >= (end - start + 1)) {
			dnstart = v->start - (end - start + 1);
			if (uadd_is_ok(dnstart, end)) {
				dnend = dnstart + end;
				if (dnstart >= USER_ALLOC_START && dnend < v->start)
					return FVSTATE_NULL_ON_PREV;
			}
		}
	}

	return FVSTATE_ERROR;
}

static int vma_where_prev_next(struct vma_desc *p, struct vma_desc *v,
					struct vma_desc *n, virt_addr_t start,
					virt_addr_t end)
{
	virt_addr_t dnstart;
	virt_addr_t dnend;
	virt_addr_t upstart;
	virt_addr_t upend;
	if (start) {
		if (start > p->end && end < v->start)
			return FVSTATE_ON_PREV;
		if (start > v->end && end < n->start)
			return FVSTATE_ON_NEXT;
	} else if (start == 0) {
		if (v->end < USER_ALLOC_END) {
			upstart = v->end + 1;
			if (uadd_is_ok(upstart, end)) {
				upend = upstart + end;
				if ((upend) < n->start && upstart > v->end)
					return FVSTATE_NULL_ON_NEXT;
			}
		}

		if (v->start >= (end - start + 1)) {
			dnstart = v->start - (end - start + 1);
			if (uadd_is_ok(dnstart, end)) {
				dnend = dnstart + end;
				if (dnstart > p->end && dnend < v->start)
					return FVSTATE_NULL_ON_PREV;
			}
		}
	}

	return FVSTATE_ERROR;
}

/**
 * 判断vma的加入位置
 */
static int vma_is_where(struct vma_desc *p, struct vma_desc *v,
					struct vma_desc *n, virt_addr_t start,
					virt_addr_t end)
{
	int ret;
	if (!v)
		return FVSTATE_ERROR;

	if (!p && v && !n) {
		ret = vma_where_onlyone(v, start, end);
		if (ret != FVSTATE_ERROR)
			return ret;
	}

	if (p && v && !n) {
		ret = vma_where_prev(p, v, start, end);
		if (ret != FVSTATE_ERROR)
			return ret;
	}

	if (!p && v && n) {
		ret = vma_where_next(v, n, start, end);
		if (ret != FVSTATE_ERROR)
			return ret;
	}

	if (p && v && n) {
		ret = vma_where_prev_next(p, v, n, start, end);
		if (ret != FVSTATE_ERROR)
			return ret;
	}

	return FVSTATE_ERROR;
}

/**
 * 查找mem中vma之间的空闲空间
 */
static int find_between_vma_freespace(struct mem_desc* m, struct vma_desc* v, 
									struct vma_desc** out, virt_addr_t start,
									virt_addr_t end)
{
	struct vma_desc *p, *n;
	int state;

	p = vma_prev(v, m);
	n = vma_next(v, m);

	state = vma_is_where(p, v, n, start, end);
	if (state != FVSTATE_ERROR) {
		*out = v;
		return state;
	}
	return FVSTATE_ERROR;
}

static int find_vma_iterator_automap(struct vma_iterator* viter)
{
	struct vma_desc *vpos = NULL, *v;
	int ret, state;
	virt_size_t size;

	if (list_is_empty(&(viter->m->vma_list))) {
		viter->vpos = NULL;
		if (viter->start) {
			viter->vposstate = FVSTATE_EMPTY;
			return 0;
		} else if (viter->start == 0) {
			viter->vposstate = FVSTATE_NULL_EMPTY;
			return 0;
		}
	}

	if (viter->start) {
		ret = find_addr_min_vma(viter->m, viter->start, &vpos);
	
		if (ret == FVSTATE_ON_PREV) {
			if (vpos && vpos->start > viter->end) {
				viter->vposstate = ret;
				viter->vpos = vpos;
				return 0;
			}
		}

		if (ret == FVSTATE_ON_NEXT) {
			if (vpos && vpos->end < viter->start) {
				viter->vposstate = ret;
				viter->vpos = vpos;
				return 0;
			}
		}
	}


	if (viter->end > viter->start) {
		size = viter->end - viter->start + 1;
		if(size >= PAGE_SIZE) {
			list_for_each_entry(v, &(viter->m->vma_list), list) {
				state = find_between_vma_freespace(viter->m, v, &vpos, 0, 0 + size - 1);
				if (state != FVSTATE_ERROR) {
					viter->vpos = vpos;
					viter->vposstate = state;
					return 0;
				}
			}
		}
	}

	viter->vposstate = FVSTATE_ERROR;
	viter->vpos = NULL;
	return FVSTATE_ERROR;
}

static int find_vma_iterator_map(struct vma_iterator* viter)
{
	struct vma_desc *vpos = NULL;
	int ret;

	if (list_is_empty(&(viter->m->vma_list))) {
		viter->vpos = NULL;
		if (viter->start) {
			viter->fiststate = FVSTATE_EMPTY;
			return 0;
		} else if (viter->start == 0) {
			viter->fiststate = FVSTATE_NULL_EMPTY;
			return 0;
		}
	}

	if (viter->start) {
		ret = find_addr_min_vma(viter->m, viter->start, &vpos);
	
		if (ret == FVSTATE_ON_PREV) {
			if (vpos && vpos->start > viter->end) {
				viter->fiststate = ret;
				viter->fisrt = vpos;
				return 0;
			}
		}

		if (ret == FVSTATE_ON_NEXT) {
			if (vpos && vpos->end < viter->start) {
				viter->fiststate = ret;
				viter->fisrt = vpos;
				return 0;
			}
		}
	}

	viter->fiststate = FVSTATE_ERROR;
	viter->fisrt = NULL;
	return FVSTATE_ERROR;
}

static int find_vma_iterator_unmap(struct vma_iterator* viter)
{
	struct vma_desc *vpos = NULL;
	int ret;
	ret = find_addr_min_vma(viter->m, viter->start, &vpos);
	BUG_ON(ret == FVSTATE_ERROR);
	viter->fiststate = ret;
	viter->fisrt = vpos;
	ret = find_addr_min_vma(viter->m, viter->end, &vpos);
	BUG_ON(ret == FVSTATE_ERROR);
	viter->laststate = ret;
	viter->last = vpos;
	return 0;
}

static int find_vma_iterator_fault(struct vma_iterator* viter)
{
	struct vma_desc *vpos = NULL;
	int ret;
	ret = find_addr_min_vma(viter->m, viter->start, &vpos);
	if (ret == FVSTATE_ADDR_IN_VMA) {
		viter->vposstate = ret;
		viter->vpos = vpos;
		return 0;
	}
	viter->vposstate = FVSTATE_ERROR;
	viter->vpos = NULL;
	return FVSTATE_ERROR;
}

static int find_vma_iterator_remap(struct vma_iterator* viter)
{
	struct vma_desc *vpos = NULL;
	int ret;
	ret = find_addr_min_vma(viter->m, viter->start, &vpos);
	if (ret == FVSTATE_ADDR_IN_VMA) {
		viter->vposstate = ret;
		viter->vpos = vpos;
		return 0;
	}
	viter->vposstate = FVSTATE_ERROR;
	viter->vpos = NULL;
	return FVSTATE_ERROR;
}

static int find_vma_iterator_mprotect(struct vma_iterator* viter)
{
	struct vma_desc *vpos = NULL;
	int ret;
	ret = find_addr_min_vma(viter->m, viter->start, &vpos);
	BUG_ON(ret == FVSTATE_ERROR);
	viter->fiststate = ret;
	viter->fisrt = vpos;
	ret = find_addr_min_vma(viter->m, viter->end, &vpos);
	BUG_ON(ret == FVSTATE_ERROR);
	viter->laststate = ret;
	viter->last = vpos;
	return 0;
}


static int find_vma_iterator_fixed(struct vma_iterator* viter)
{
	struct vma_desc *vpos = NULL;
	int ret;
	ret = find_addr_min_vma(viter->m, viter->start, &vpos);
	BUG_ON(ret == FVSTATE_ERROR);
	viter->fiststate = ret;
	viter->fisrt = vpos;
	ret = find_addr_min_vma(viter->m, viter->end, &vpos);
	BUG_ON(ret == FVSTATE_ERROR);
	viter->laststate = ret;
	viter->last = vpos;
	return 0;
}

int find_vma_iterator(struct vma_iterator* viter, int flags)
{
	if (!viter || !viter->m)
		return -EINVAL;
	if (flags == FVFLAG_MAP)
		return find_vma_iterator_map(viter);
	if (flags == FVFLAG_AUTOMAP)
		return find_vma_iterator_automap(viter);
	if (flags == FVFLAG_FIXED)
		return find_vma_iterator_fixed(viter);
	if (flags == FVFLAG_UNMAP)
		return find_vma_iterator_unmap(viter);
	if (flags == FVFLAG_FAULT)
		return find_vma_iterator_fault(viter);
	if (flags == FVFLAG_REMAP)
		return find_vma_iterator_remap(viter);
	if (flags == FVFLAG_MPROTECT)
		return find_vma_iterator_mprotect(viter);
	return -EFAULT;
}

/**
 * 解除vma区间对应的页面
 */
int vmem_unmap_vma_pages(struct mem_desc *m, struct vma_desc *v, virt_addr_t start,
	virt_addr_t end)
{
	struct mmu_walk_info info;
	if (!m || !v || !start || !end)
		return -EINVAL;
	if (start < v->start || end > v->end)
		return -EINVAL;
	memset(&info, 0, sizeof(info));

	info.in_mmu = &m->mem_arch.mmu;
	info.in_umstart = start;
	info.in_umend = end;
	if (mmu_unmap_range(&info))
		return -EFAULT;
	return 0;
}


static int direct_destroy_vma(struct mem_desc *m, struct vma_desc *v, virt_addr_t start,
	virt_addr_t end)
{
	if (!m || !v)
		return -EINVAL;
	if (v->start != start || v->end != end)
		return -EINVAL;

	if (vmem_unmap_vma_pages(m, v, v->start, v->end))
		return -EFAULT;

	/**
	 * 小心行事，删除vma后，一定要检查vma_cache
	 * 如果相等就要设置为NULL
	 */
	if (m->vma_cache == v)
		set_vma_cache(m, NULL);

	list_del_init(&v->list);
	free_vma_desc(v);
	return 0;
}

static int modify_destroy_vma(struct mem_desc *m, struct vma_desc *v,
	virt_addr_t start, virt_addr_t end)
{
	if (!m || !v)
		return -EINVAL;

	if (v->start > start || v->end < end)
		return -EINVAL;

	if (v->start == start && end < v->end) {
		if (vmem_unmap_vma_pages(m, v, start, end))
			return -EFAULT;
		v->start = end + 1;
		/**
		 * 处理文件偏移
		 */
		if (v->file)
			v->offset = v->offset + (end + 1 - start);

		return 0;
	}

	if (v->start < start && v->end == end) {
		if (vmem_unmap_vma_pages(m, v, start, end))
			return -EFAULT;
		v->end = start - 1;
		return 0;
	}

	if (v->start < start && v->end > end) {
		struct vma_desc *out, *vma = alloced_vma_desc();
		if (!vma)
			return -ENOMEM;
		if (vmem_unmap_vma_pages(m, v, start, end)) {
			free_vma_desc(vma);
			return -EFAULT;
		}

		memcpy((void *)vma, (const void *)v, sizeof(*vma));
		list_init(&vma->list);
		RB_NODE_INIT(&vma->rbnode);
		smp_lock_init(&vma->lock);

		vma->end = v->end;
		v->end = start - 1;
		vma->start = end + 1;
		/**
		 * 处理文件偏移
		 */
		if (vma->file)
			vma->offset = v->offset + (v->end + 1 - v->start) + (end + 1 - start);

		BUG_ON(!insert_vma_desc(m, &out, v, vma, FVSTATE_ON_NEXT));
		return 0;
	}
	return -EFAULT;
}


static int unmap_onevma_vmaiterator(struct vma_iterator* viter, struct vma_desc* vma)
{
	if (!viter || !vma)
		return -EINVAL;
	if (vma->start < viter->start && 
			viter->start < vma->end && viter->end >= vma->end) {
		return modify_destroy_vma(viter->m, vma, viter->start, vma->end);
	}

	if (vma->start < viter->end && 
			viter->end < vma->end && viter->start <= vma->start) {
		return modify_destroy_vma(viter->m, vma, vma->start, viter->end);
	}

	if (vma->start < viter->start && viter->end < vma->end) {
		return modify_destroy_vma(viter->m, vma, viter->start, viter->end);
	}
	
	if (vma->start >= viter->start && viter->end >= vma->end) {
		return direct_destroy_vma(viter->m, vma, vma->start, vma->end);
	}

	return -EFAULT;
}

static int unmap_vmas_range_vmaiterator(struct vma_iterator* viter)
{
	struct vma_desc* v, *n;
	if (!viter || !viter->m)
		return -EINVAL;
	if (fixed_addrspace_is_free(viter))
		return 0;

	if (viter->fisrt == viter->last) {
		BUG_ON(unmap_onevma_vmaiterator(viter, viter->fisrt));
		return 0;
	}

	BUG_ON(viter->fiststate != FVSTATE_ADDR_IN_VMA && viter->fiststate != FVSTATE_ON_PREV);
	BUG_ON(viter->laststate != FVSTATE_ADDR_IN_VMA && viter->laststate != FVSTATE_ON_PREV);

	for (v = viter->fisrt; v->start < viter->end; ) {
		n = vma_next(v, viter->m);
		
		BUG_ON(unmap_onevma_vmaiterator(viter, v));
		if (n)
			v = n;
		else
		 	break;
	}

	return 0;
}

static int identify_opt_freevmastate_vmaiterator(struct vma_iterator* viter)
{
	struct vma_desc* vma;
	if (!viter)
		return -EINVAL;

	vma = viter->fisrt;
	if (viter->fiststate == FVSTATE_EMPTY || !vma) {
		viter->vpos = NULL;
		viter->vposstate = viter->fiststate;
		return 0;
	}

	if (viter->end < vma->start) {
		viter->vpos = vma;
		viter->vposstate = FVSTATE_ON_PREV;
		return 0;
	}

	if (viter->start > vma->end) {
		viter->vpos = vma;
		viter->vposstate = FVSTATE_ON_NEXT;
		return 0;
	}

	return -EFAULT;
}

static void *create_vma_not_fixed(struct mem_desc *m, struct vma_desc **out,
							virt_addr_t start, virt_addr_t end,
							u64 access, u64 flags, void *file,
							off_t offset)
{
	struct vma_desc *v, *vpos;
	struct vma_iterator viter;

	virt_addr_t addr_start;
	void *ret = NULL;
	int state;

	addr_start = start;
	/**
	 * 这样的加锁非常粗暴，以后优化
	 */
	down_write(&m->rwsem);
	
	/**
	 * 根据虚拟地址查找vma
	 */
	vma_iterator_init(&viter, m, addr_start, end);
	if (find_vma_iterator(&viter, FVFLAG_AUTOMAP)) {
		ret = NULL;
		goto unlock;
	}
	
	vpos = viter.vpos;

	state = vma_is_extn(m, viter.vpos, viter.vposstate, addr_start, end, access, flags, file, offset);
	/**
	 * 处理vma_desc可扩展的情况
	 * 而不是每次分配一个新的vma_desc，浪费内存
	 */
	if (state == FVSTATE_DN_EXT ||
		state == FVSTATE_UP_EXT ||
		state == FVSTATE_NULL_DN_EXT ||
		state == FVSTATE_NULL_UP_EXT) {
		ret = exten_vma_desc(vpos, out, state, addr_start, end);
		set_vma_cache(m, vpos);
		goto unlock;
	}
	/**
	 * 分配新的vma
	 */
	v = alloced_vma_desc();
	if (!v) {
		ret = NULL;
		*out = NULL;
		goto unlock;
	}

	/**
	 * 设置vma
	 */
	ret = set_new_vma_desc(m, v, vpos, state, addr_start, end, access, flags, file, offset);
	if (!ret)
		goto free_vma;

	/**
	 * 插入vma
	 */
	ret = insert_vma_desc(m, out, vpos, v, state);
	if (ret) {
		set_vma_cache(m, v);
		goto unlock;
	}

free_vma:
	*out = NULL;
	ret = NULL;
	free_vma_desc(v);

unlock:
	up_write(&m->rwsem);
	return ret;
}

static void *create_vma_not_fixed_unlock(struct mem_desc *m, struct vma_desc **out,
							virt_addr_t start, virt_addr_t end,
							u64 access, u64 flags, void *file,
							off_t offset)
{
	struct vma_desc *v, *vpos;
	struct vma_iterator viter;

	virt_addr_t addr_start;
	void *ret = NULL;
	int state;

	addr_start = start;
	
	/**
	 * 根据虚拟地址查找vma
	 */
	vma_iterator_init(&viter, m, addr_start, end);
	if (find_vma_iterator(&viter, FVFLAG_AUTOMAP)) {
		ret = NULL;
		return ret;
	}
	
	vpos = viter.vpos;

	state = vma_is_extn(m, viter.vpos, viter.vposstate, addr_start, end, access, flags, file, offset);
	/**
	 * 处理vma_desc可扩展的情况
	 * 而不是每次分配一个新的vma_desc，浪费内存
	 */
	if (state == FVSTATE_DN_EXT ||
		state == FVSTATE_UP_EXT ||
		state == FVSTATE_NULL_DN_EXT ||
		state == FVSTATE_NULL_UP_EXT) {
		ret = exten_vma_desc(vpos, out, state, addr_start, end);
		set_vma_cache(m, vpos);
		return ret;
	}
	/**
	 * 分配新的vma
	 */
	v = alloced_vma_desc();
	if (!v) {
		ret = NULL;
		*out = NULL;
		return ret;
	}

	/**
	 * 设置vma
	 */
	ret = set_new_vma_desc(m, v, vpos, state, addr_start, end, access, flags, file, offset);
	if (!ret)
		goto free_vma;

	/**
	 * 插入vma
	 */
	ret = insert_vma_desc(m, out, vpos, v, state);
	if (ret) {
		set_vma_cache(m, v);
		return ret;
	}

free_vma:
	*out = NULL;
	ret = NULL;
	free_vma_desc(v);

	return ret;
}

static void *create_vma_fixed(struct mem_desc *m, struct vma_desc **out,
							virt_addr_t start, virt_addr_t end,
							u64 access, u64 flags, void *file,
							off_t offset)
{
	struct vma_desc *v, *vpos;
	struct vma_iterator viter;
	virt_addr_t addr_start;
	void *ret = NULL;
	int state;

	addr_start = start;
	/**
	 * 这样的加锁非常粗暴，以后优化
	 */
	down_write(&m->rwsem);

	vma_iterator_init(&viter, m, addr_start, end);
	
	if (find_vma_iterator(&viter, FVFLAG_FIXED)) {
		ret = NULL;
		goto unlock;
	}

	if (!fixed_addrspace_is_free(&viter)) {
		if (flags & VAF_FIXED_NOREPLACE_MAP) {
			ret = NULL;
			goto unlock;
		}
		if (unmap_vmas_range_vmaiterator(&viter)) {
			ret = NULL;
			goto unlock;
		}

		/**
		 * 重新以map方式查找
		 */
		vma_iterator_init(&viter, m, addr_start, end);
	
		if (find_vma_iterator(&viter, FVFLAG_MAP)) {
			ret = NULL;
			goto unlock;
		}
	}

	if (identify_opt_freevmastate_vmaiterator(&viter)) {
		ret = NULL;
		goto unlock;
	}

	vpos = viter.vpos;
	state = vma_is_extn(m, viter.vpos, viter.vposstate, addr_start, end, access, flags, file, offset);
	/**
	 * 处理vma_desc可扩展的情况
	 * 而不是每次分配一个新的vma_desc，浪费内存
	 */
	if (state == FVSTATE_DN_EXT ||
		state == FVSTATE_UP_EXT ||
		state == FVSTATE_NULL_DN_EXT ||
		state == FVSTATE_NULL_UP_EXT) {
		ret = exten_vma_desc(vpos, out, state, addr_start, end);
		set_vma_cache(m, vpos);
		goto unlock;
	}
	/**
	 * 分配新的vma
	 */
	v = alloced_vma_desc();
	if (!v) {
		ret = NULL;
		*out = NULL;
		goto unlock;
	}

	/**
	 * 设置vma
	 */
	ret = set_new_vma_desc(m, v, vpos, state, addr_start, end, access, flags, file, offset);
	if (!ret)
		goto free_vma;

	/**
	 * 插入vma
	 */
	ret = insert_vma_desc(m, out, vpos, v, state);
	if (ret) {
		set_vma_cache(m, v);
		goto unlock;
	}

free_vma:
	*out = NULL;
	ret = NULL;
	free_vma_desc(v);

unlock:
	up_write(&m->rwsem);
	return ret;
}

static void *create_vma_fixed_unlock(struct mem_desc *m, struct vma_desc **out,
							virt_addr_t start, virt_addr_t end,
							u64 access, u64 flags, void *file,
							off_t offset)
{
	struct vma_desc *v, *vpos;
	struct vma_iterator viter;
	virt_addr_t addr_start;
	void *ret = NULL;
	int state;

	addr_start = start;

	vma_iterator_init(&viter, m, addr_start, end);
	
	if (find_vma_iterator(&viter, FVFLAG_FIXED)) {
		ret = NULL;
		return ret;
	}

	if (!fixed_addrspace_is_free(&viter)) {
		if (flags & VAF_FIXED_NOREPLACE_MAP) {
			ret = NULL;
			return ret;
		}
		if (unmap_vmas_range_vmaiterator(&viter)) {
			ret = NULL;
			return ret;
		}

		/**
		 * 重新以map方式查找
		 */
		vma_iterator_init(&viter, m, addr_start, end);
	
		if (find_vma_iterator(&viter, FVFLAG_MAP)) {
			ret = NULL;
			return ret;
		}
	}

	if (identify_opt_freevmastate_vmaiterator(&viter)) {
		ret = NULL;
		return ret;
	}

	vpos = viter.vpos;
	state = vma_is_extn(m, viter.vpos, viter.vposstate, addr_start, end, access, flags, file, offset);
	/**
	 * 处理vma_desc可扩展的情况
	 * 而不是每次分配一个新的vma_desc，浪费内存
	 */
	if (state == FVSTATE_DN_EXT ||
		state == FVSTATE_UP_EXT ||
		state == FVSTATE_NULL_DN_EXT ||
		state == FVSTATE_NULL_UP_EXT) {
		ret = exten_vma_desc(vpos, out, state, addr_start, end);
		set_vma_cache(m, vpos);
		return ret;
	}
	/**
	 * 分配新的vma
	 */
	v = alloced_vma_desc();
	if (!v) {
		ret = NULL;
		*out = NULL;
		return ret;
	}

	/**
	 * 设置vma
	 */
	ret = set_new_vma_desc(m, v, vpos, state, addr_start, end, access, flags, file, offset);
	if (!ret)
		goto free_vma;

	/**
	 * 插入vma
	 */
	ret = insert_vma_desc(m, out, vpos, v, state);
	if (ret) {
		set_vma_cache(m, v);
		return ret;
	}

free_vma:
	*out = NULL;
	ret = NULL;
	free_vma_desc(v);

	return ret;
}

/**
 * 创建虚拟地址区间实现---无锁版本
 */
static void *create_vma_core_unlock(struct mem_desc *m, struct vma_desc **out,
							virt_addr_t start, virt_addr_t end,
							u64 access, u64 flags, void *file,
							off_t offset)
{
	if (!(flags & VAF_FIXED_MAP) && 
					!(flags & VAF_FIXED_NOREPLACE_MAP)) {
		return create_vma_not_fixed_unlock(m, out, start, end, 
							access, flags, file, offset);
	} else if ((flags & VAF_FIXED_MAP) || 
					(flags & VAF_FIXED_NOREPLACE_MAP)) {
		return create_vma_fixed_unlock(m, out, start, end, 
							access, flags, file, offset);
	}
	return NULL;
}

/**
 * 创建虚拟地址区间实现
 */
static void *create_vma_core(struct mem_desc *m, struct vma_desc **out,
							virt_addr_t start, virt_addr_t end,
							u64 access, u64 flags, void *file,
							off_t offset)
{
	if (!(flags & VAF_FIXED_MAP) && 
					!(flags & VAF_FIXED_NOREPLACE_MAP)) {
		return create_vma_not_fixed(m, out, start, end, 
							access, flags, file, offset);
	} else if ((flags & VAF_FIXED_MAP) || 
					(flags & VAF_FIXED_NOREPLACE_MAP)) {
		return create_vma_fixed(m, out, start, end, 
							access, flags, file, offset);
	}
	return NULL;
}

/**
 * 创建虚拟地址区间
 */
void *create_vma(struct mem_desc *m, struct vma_desc **out,
					virt_addr_t start, virt_size_t size, u64 access,
					u64 flags, void *file, off_t offset)
{
	u64 t_access, t_flags;
	void *ret;
	struct vma_desc *retvma;
	virt_addr_t start_addr, end_addr;
	void *t_file = file;
	off_t t_offset = offset;

	if (!m || !size || !flags)
		return NULL;

	t_access = mmapprot_to_vmaacces((unsigned long)access);
	t_flags = mmapflags_to_vmaflags((unsigned long)flags);
	
	if ((t_flags & VAF_ANONYMOUS_MAP) && (t_flags & VAF_FILE_MAP))
		return NULL;

	if (t_flags & VAF_ANONYMOUS_MAP) {
		t_file = NULL;
		t_offset = 0;
	}

	if (t_flags & VAF_FILE_MAP) {
		if (!t_file)
			return NULL;
	}

	if ((t_flags & VAF_FIXED_MAP) || (t_flags & VAF_FIXED_NOREPLACE_MAP)) {
		if (!start || (start & ~PAGE_MASK)) {
			return NULL;
		}
	}

	/**
	 * 注意溢出
	 */
	if (!uadd_is_ok(start, size))
		return NULL;

	start_addr = start & PAGE_MASK;
	end_addr = PAGE_ALIGN(start_addr + size) - 1;

	if (end_addr >= USER_ALLOC_END)
		return NULL;

	
	ret = create_vma_core(m, &retvma, start_addr, end_addr,
				 t_access, t_flags, t_file, t_offset);
	if (!ret || !retvma) {
		if (out)
			*out = retvma;
		return NULL;
	}

	if (out)
		*out = retvma;

	return ret;
}

/**
 * 创建虚拟地址区间 --- 无锁版本
 */
void *create_vma_unlock(struct mem_desc *m, struct vma_desc **out,
					virt_addr_t start, virt_size_t size, u64 access,
					u64 flags, void *file, off_t offset)
{
	u64 t_access, t_flags;
	void *ret;
	struct vma_desc *retvma;
	virt_addr_t start_addr, end_addr;
	void *t_file = file;
	off_t t_offset = offset;

	if (!m || !size || !flags)
		return NULL;

	t_access = mmapprot_to_vmaacces((unsigned long)access);
	t_flags = mmapflags_to_vmaflags((unsigned long)flags);
	
	if ((t_flags & VAF_ANONYMOUS_MAP) && (t_flags & VAF_FILE_MAP))
		return NULL;

	if (t_flags & VAF_ANONYMOUS_MAP) {
		t_file = NULL;
		t_offset = 0;
	}

	if (t_flags & VAF_FILE_MAP) {
		if (!t_file)
			return NULL;
	}

	if ((t_flags & VAF_FIXED_MAP) || (t_flags & VAF_FIXED_NOREPLACE_MAP)) {
		if (!start || (start & ~PAGE_MASK)) {
			return NULL;
		}
	}

	/**
	 * 注意溢出
	 */
	if (!uadd_is_ok(start, size))
		return NULL;

	start_addr = start & PAGE_MASK;
	end_addr = PAGE_ALIGN(start_addr + size) - 1;

	if (end_addr >= USER_ALLOC_END)
		return NULL;

	
	ret = create_vma_core_unlock(m, &retvma, start_addr, end_addr,
				 t_access, t_flags, t_file, t_offset);
	if (!ret || !retvma) {
		if (out)
			*out = retvma;
		return NULL;
	}

	if (out)
		*out = retvma;

	return ret;
}

static void *copy_vma(struct mem_desc *dst_m, struct vma_desc **out, struct vma_desc *src_vma)
{
	struct vma_desc *dst_vma, *vpos;
	struct vma_iterator viter;
	int state;
	void *ret;

	/* 1. 申请 vma 内存*/

	dst_vma = alloced_vma_desc();
	if (!dst_vma)
		goto failed;

	/* 2. 完全拷贝 vma, 这里需要加锁读 src_vma */
	smp_lock(&src_vma->lock);
	*dst_vma = *src_vma;
	smp_unlock(&src_vma->lock);

	/* 3. 对特定属性需要特别赋值 */
	list_init(&dst_vma->list);
	RB_NODE_INIT(&dst_vma->rbnode);
	smp_lock_init(&dst_vma->lock);
	dst_vma->at_mem = dst_m;

	/* pr_info("copy_vma : vma addr:[%lx] vma start:[%lx] end:[%lx] type:[%s], mm:[%lx]\n",
	 *		dst_vma, dst_vma->start, dst_vma->start,
	 *		get_vma_type_string(dst_vma), dst_vma->at_mem);
	 */

	/* 4. 在锁的保护下插入 vma */
	down_write(&dst_m->rwsem);

	vma_iterator_init(&viter, dst_m, dst_vma->start, dst_vma->end);
	
	if (find_vma_iterator(&viter, FVFLAG_MAP)) {
		ret = NULL;
		goto unlock;
	}

	if (identify_opt_freevmastate_vmaiterator(&viter)) {
		ret = NULL;
		goto unlock;
	}

	vpos = viter.vpos;
	state = viter.vposstate;

	ret = insert_vma_desc(dst_m, out, vpos, dst_vma, state);
	if (ret)
		set_vma_cache(dst_m, dst_vma);
	up_write(&dst_m->rwsem);
	return ret;
unlock:
	up_write(&dst_m->rwsem);
failed:
	*out = NULL;
	if (dst_vma) free_vma_desc(dst_vma);
	return NULL;
}

/**
 * 拷贝页表
 */
static int copy_vma_mmu(struct vma_desc *dst_vma, struct vma_desc *src_vma, int code)
{
	struct mmu_walk_info dst_info, src_info;
	struct page_frame *page;
	unsigned long prot = 0;
	virt_addr_t vaddr;
	int ret = 0;

	if (!dst_vma || !src_vma || !dst_vma->at_mem || !src_vma->at_mem)
		return -EINVAL;
	/* 1. 初始化 dst 与 src mmu 通用属性 */
	memset(&dst_info, 0x0, sizeof(dst_info));
	dst_info.in_mmu = &dst_vma->at_mem->mem_arch.mmu;

	memset(&src_info, 0x0, sizeof(src_info));
	src_info.in_mmu = &src_vma->at_mem->mem_arch.mmu;

	if (!code) {
		prot = PROT_READ | PROT_USER;
	} else {
		prot = PROT_EXEC | PROT_READ | PROT_USER;
	}

	//如果是共享内存，那么不需要修改权限
	if (src_vma->flags & VAF_SHARED_MAP) {
		mmu_set_info_prot(&dst_info, src_vma->acces);
		mmu_set_info_prot(&src_info, src_vma->acces);
	} else {
		mmu_walk_info_set_prot(&dst_info, prot);
		mmu_walk_info_set_prot(&src_info, prot);
	}

	/* 2. 遍历所有虚拟页, 根据源虚拟页是否映射来判断是否拷贝 */
	for (vaddr = src_vma->start; vaddr < src_vma->end; vaddr += PAGE_SIZE) {
		/* 2.1 设置要查询的虚拟地址 */
		src_info.in_faddr = dst_info.in_faddr = vaddr;
		/* 2.2 查询虚拟地址,并根据虚拟地址判断是否要拷贝 */
		ret = mmu_find_ttbl(&src_info);
		if (!ret) {
			/* printk("copy_vma_mmu copy, vaddr[%lx], bind phys addr[%lx]\n",
			vaddr, src_info.out_l4); */

			/* 2.3 创建 dst mmu 虚拟地址所需要的四级页表 */
			ret = mmu_ttbl_fault(&dst_info);
			if (ret != MMU_MAP_L3_TBL) {
				printk("mmu_ttbl_fault error\n\n\n");
				BUG();
				return -ENOMEM;
			}
			/* 2.4 将两个虚拟页映射在一个物理页上,并将其设置为只读(写时拷贝),
			这里需要增加 page 的引用计数  */
			page = phys_addr_to_page((phys_addr_t)src_info.out_l4);
			hold_page(page);
			src_info.in_paddr = dst_info.in_paddr = (phys_addr_t)src_info.out_l4;
			ret = mmu_complete_map(&dst_info);
			ret = mmu_complete_map(&src_info);
		}
	}
	return 0;
}

/**
 * VMEM匿名映射和文件映射
 */
unsigned long vmem_mmap(void *addr, size_t len, int fd, off_t offset, u64 access, u64 flags)
{
	struct mem_desc *m;
	unsigned long ret = -1;
	void *file, *retaddr;
	m = current_mem;
	file = get_file_on_fd(fd);
	retaddr = create_vma(m, NULL, (virt_addr_t)addr, len,
					access, flags, file, offset);
	if (retaddr)
		ret = (unsigned long)retaddr;
	return ret;
}

/**
 * VMEM匿名映射和文件映射
 */
unsigned long vmem_mmap_on_file(struct file *file, virt_addr_t addr,
	virt_size_t len, u64 access, u64 flags, off_t offset)
{
	struct mem_desc *m = current_mem;
	unsigned long ret = -1;
	void *retaddr;
	retaddr = create_vma(m, NULL, (virt_addr_t)addr, len,
					access, flags, file, offset);
	if (retaddr)
		ret = (unsigned long)retaddr;
	return ret;
}

/**
 * VMEM匿名映射和文件映射 --- 无锁版本
 */
unsigned long vmem_mmap_on_file_unlock(struct file *file, virt_addr_t addr,
	virt_size_t len, u64 access, u64 flags, off_t offset)
{
	struct mem_desc *m = current_mem;
	unsigned long ret = -1;
	void *retaddr;
	retaddr = create_vma_unlock(m, NULL, (virt_addr_t)addr, len,
					access, flags, file, offset);
	if (retaddr)
		ret = (unsigned long)retaddr;
	return ret;
}


struct vma_desc* vmem_mmap_ret_vma(void *addr, size_t len, int fd, off_t offset, u64 access, u64 flags)
{
	struct mem_desc *m;
	struct vma_desc *ret = NULL;
	void *file, *retaddr;
	m = current_mem;
	file = get_file_on_fd(fd);
	retaddr = create_vma(m, &ret, (virt_addr_t)addr, len,
					access, flags, file, offset);
	if (!retaddr)
		ret = NULL;
	return ret;
}

/**
 * 堆空间的解除映射操作
 */
static int vmem_heap_unmap(struct mem_desc *m, struct vma_desc *v, virt_addr_t start,
	virt_addr_t end)
{
	if (start < v->start || end > v->heapend)
		return -EINVAL;

	return vmem_unmap_vma_pages(m, v, start, end);
}

/**
 * 堆的扩展操作
 */
static void *vmem_heap_extension(struct mem_desc *m, struct vma_desc *v, virt_size_t size,
	int direction)
{
	virt_size_t t_sz;
	void *ret = NULL;
	if (!m || !v || direction > 1)
		return NULL;
	if (!vma_is_heap(v))
		return NULL;

	down_write(&m->rwsem);

	t_sz = (size);

	if (direction == VMA_EXT_UP) {
		if (v->heapend + (virt_addr_t)t_sz > v->end) {
			ret = NULL;
			goto unlock;
		}
		v->heapend += (off_t)t_sz;
		ret = (void *)v->heapend;
		goto unlock;
	}
	if (direction == VMA_EXT_DN) {
		if (v->heapend - (virt_addr_t)t_sz < v->start) {
			ret = NULL;
			goto unlock;
		}

		if (vmem_heap_unmap(m, v, v->heapend - t_sz,
									v->heapend - 1)) {
			ret = NULL;
			goto unlock;
		}

		v->heapend -= (virt_addr_t)t_sz;
		ret = (void *)v->heapend;
		goto unlock;
	}

unlock:
	up_write(&m->rwsem);
	return ret;
}



/**
 * 非安全未加锁的销毁虚拟地址区间
 * 注意！！此接口只能在特定的环境中使用
 * 并不是一个通用的外部接口
 */
/**
 * 无锁销毁虚拟地址区间实现
 */
static int unsafe_destroy_vma_core(struct mem_desc *m, virt_addr_t start, virt_addr_t end)
{
	struct vma_iterator viter;
	
	if (start >= end) 
		return -EINVAL;

	vma_iterator_init(&viter, m, start, end);
	
	if (find_vma_iterator(&viter, FVFLAG_UNMAP))
		return -EFAULT;

	if (unmap_vmas_range_vmaiterator(&viter))
		return -EFAULT;

	return 0;
}

/**
 * 销毁虚拟地址区间实现
 */
static int destroy_vma_core(struct mem_desc *m, virt_addr_t start, virt_addr_t end)
{
	int ret = -EFAULT;
	/**
	 * 这样的加锁非常粗暴，以后优化
	 */
	down_write(&m->rwsem);

	ret = unsafe_destroy_vma_core(m, start, end);

	up_write(&m->rwsem);
	return ret;
}

/**
 * 销毁虚拟地址区间
 */
int destroy_vma(struct mem_desc *m, virt_addr_t start, virt_size_t size)
{
	virt_addr_t start_addr, end_addr;
	virt_size_t t_size = size;
	if (!m || !start)
		return -EINVAL;

	/**
	 * 至少为一页
	 */
	if (!t_size)
		t_size = PAGE_SIZE;

	/**
	 * 注意溢出
	 */
	if (!uadd_is_ok(start, t_size))
		return -EFAULT;

	start_addr = start & PAGE_MASK;
	end_addr = PAGE_ALIGN(start + t_size) - 1;

	if (end_addr >= USER_ALLOC_END)
		return -EFAULT;
	return destroy_vma_core(m, start_addr, end_addr);
}

/**
 * 销毁虚拟地址区间---无锁版本
 */
int destroy_vma_unlock(struct mem_desc *m, virt_addr_t start, virt_size_t size)
{
	virt_addr_t start_addr, end_addr;
	virt_size_t t_size = size;
	if (!m || !start)
		return -EINVAL;

	/**
	 * 至少为一页
	 */
	if (!t_size)
		t_size = PAGE_SIZE;

	/**
	 * 注意溢出
	 */
	if (!uadd_is_ok(start, t_size))
		return -EFAULT;

	start_addr = start & PAGE_MASK;
	end_addr = PAGE_ALIGN(start + t_size) - 1;

	if (end_addr >= USER_ALLOC_END)
		return -EFAULT;
	return unsafe_destroy_vma_core(m, start_addr, end_addr);
}

/**
 * VMEM解除匿名映射和文件映射
 */
int vmem_munmmap(void *addr, size_t len)
{
	struct mem_desc *m;
	m = current_mem;
	return destroy_vma(m, (virt_addr_t)addr, (virt_size_t)len);
}

/**
 * 创建用户堆栈对应虚拟地址区间
 */
int create_userheapstack_vma(struct mem_desc *m)
{
	struct vma_desc *stackvma, *heapvma, *envvma;
	void *ret;
	if (!m)
		return -EINVAL;

	ret = create_vma(m, &heapvma, USER_HEAP_START, USER_HEAP_SIZE,
				 URW_PROT, HEAP_MAP_FLAGS, NULL, 0);
	if (!ret)
		return -ENOMEM;
	ret = create_vma(m, &stackvma, USER_STACK_START, USER_STACK_SIZE,
				 URW_PROT, STACK_MAP_FLAGS, NULL, 0);
	if (!ret)
		return -ENOMEM;

	ret = create_vma(m, &envvma, USER_ENV_START, USER_ENV_SIZE,
				 URW_PROT, ENV_MAP_FLAGS, NULL, 0);
	if (!ret)
		return -ENOMEM;

	smp_lock(&m->lock);
	m->vma_stack = stackvma;
	m->vma_heap = heapvma;
	m->vma_env = envvma;
	heapvma->heapend = heapvma->start;
	smp_unlock(&m->lock);
	return 0;
}

static int copy_userheapstack_vma(struct mem_desc *dst, struct mem_desc *src)
{
	struct vma_desc *stackvma, *heapvma, *envvma;
	void *ret;
	int err = -EFAULT;
	if (!dst)
		return -EINVAL;
	ret = copy_vma(dst, &heapvma, src->vma_heap);
	if (!ret)
		goto failed;
	ret = copy_vma(dst, &stackvma, src->vma_stack);
	if (!ret)
		goto failed;
	ret = copy_vma(dst, &envvma, src->vma_env);
	if (!ret)
		goto failed;

	smp_lock(&dst->lock);
	dst->vma_stack = stackvma;
	dst->vma_heap = heapvma;
	dst->vma_env = envvma;
	smp_unlock(&dst->lock);

	/**
	 * 拷贝页表
	 */
	err = copy_vma_mmu(dst->vma_stack, src->vma_stack, 0);
	if (err)
		goto failed;
	err = copy_vma_mmu(dst->vma_heap, src->vma_heap, 0);
	if (err)
		goto failed;
	/**
	 * 由于env内容是存放在stack里面的，不需要单独拷贝。
	 */

	return 0;
failed:
	return err;
}

static int destroy_userheapstack_vma(struct mem_desc *m)
{
	int ret;
	if (!m)
		return -EINVAL;

	ret = direct_destroy_vma(m, m->vma_stack, m->vma_stack->start, m->vma_stack->end);
	if (ret)
		return -EFAULT;
	ret = direct_destroy_vma(m, m->vma_heap, m->vma_heap->start, m->vma_heap->end);
	if (ret)
		return -EFAULT;
	ret = direct_destroy_vma(m, m->vma_env, m->vma_env->start, m->vma_env->end);
	if (ret)
		return -EFAULT;

	smp_lock(&m->lock);
	m->vma_stack = NULL;
	m->vma_heap = NULL;
	m->vma_env = NULL;
	smp_unlock(&m->lock);
	return 0;
}

static int copy_exec_vma(struct mem_desc *dst, struct mem_desc *src)
{
	void* ret;
	int err = -EFAULT;
	struct vma_desc *src_vma, *tmp;

	if (!dst || !src)
		return -EINVAL;

	list_for_each_entry(src_vma, &src->vma_list, list) {
		if (src_vma != src->vma_stack && src_vma != src->vma_heap &&
			src_vma != src->vma_env) {
			ret = copy_vma(dst, &tmp, src_vma);
			if (!ret)
				return -ENOMEM;

			/* pr_info("copy_exec_vma vma start:
			 *		[%lx, %lx] end:[%lx, %lx] type:[%s, %s], mm:[%lx,%lx]\n",
			 *		src_vma->start, tmp->start, src_vma->end,
			 *		tmp->end, get_vma_type_string(src_vma),
			 *		get_vma_type_string(tmp), src_vma->at_mem, tmp->at_mem);
			 */
			err = copy_vma_mmu(tmp, src_vma, src_vma->acces & VAC_EXEC);
			if (err)
				return -ENOMEM;
		}
	}
	return 0;
}

static int destroy_exec_vma(struct mem_desc *mm)
{
	int ret;
	struct vma_desc *vma, *n;
	if (!mm)
		return -EINVAL;

	list_for_each_entry_safe(vma, n, &mm->vma_list, list) {
		if (vma != mm->vma_stack && vma != mm->vma_heap && vma != mm->vma_env) {
			/* pr_info("destroy_exec_vma vma start:[%lx] end:[%lx] type:[%s],
					mm:[%lx]\n",
			 *		vma->start, vma->end,
					get_vma_type_string(vma), vma->at_mem);
			 */
			ret = direct_destroy_vma(mm, vma, vma->start, vma->end);
			if (ret)
				return -ENOMEM;
		}
	}
	return 0;
}

/**
 * 创建进程虚拟地址
 */
int create_process_vma(struct process_desc *proc)
{
	struct mem_desc *m;
	int ret;
	if (!proc || !proc->mem)
		return -EINVAL;

	m = proc->mem;
	ret = create_userheapstack_vma(m);
	if (ret)
		return -ENOMEM;
	return 0;
}

static int copy_process_vma(struct process_desc *dst, struct process_desc *src)
{
	int ret;
	struct mem_desc *dst_m, *src_m;
	if (!dst || !src || !dst->mem || !src->mem)
		return -EINVAL;
	dst_m = dst->mem;
	src_m = src->mem;
	ret = copy_userheapstack_vma(dst_m, src_m);
	if (ret)
		return ret;
	ret = copy_exec_vma(dst_m, src_m);
	if (ret)
		return ret;
	return 0;
}

static int destroy_process_vma(struct process_desc *proc)
{
	struct mem_desc *m;
	int ret;
	if (!proc || !proc->mem)
		return -EINVAL;
	m = proc->mem;
	/**
	 * 暂时必须先释放 exec vma,
	 * 因为要根据 userheadstack vma
	 * 判断哪些是 exec vma
	 */
	ret = destroy_exec_vma(m);
	if (ret)
		return ret;
	/* debug_memspace(proc->mem); */
	ret = destroy_userheapstack_vma(m);
	if (ret)
		return ret;
	/* debug_memspace(proc->mem); */
	return 0;
}

/**
 * 创建进程mmu
 */
int create_process_mmu(struct process_desc *proc)
{
	return mmu_create(proc);
}

/**
 * 创建进程内存地址空间
 */
int create_process_memspace(struct process_desc *proc)
{
	int ret;
	if (!proc)
		return -EINVAL;

	ret = create_mem_desc(proc);
	if (ret)
		return ret;
	ret = create_process_mmu(proc);
	if (ret)
		return ret;
	ret = create_process_vma(proc);
	if (ret)
		return ret;
	return 0;
}

int copy_process_memspace(struct process_desc *dst)
{
	int ret;
	if (!dst)
		return -EINVAL;

	ret = create_mem_desc(dst);
	if (ret)
		return ret;
	ret = create_process_mmu(dst);
	if (ret)
		return ret;
	ret = copy_process_vma(dst, current_proc_info());
	if (ret)
		return ret;
	return 0;
}

__maybe_unused static void debug_memspace(struct mem_desc *m)
{
	struct vma_desc *v;
	printk("debug_memspace begin ====\n\n\n");
	list_for_each_entry(v, &m->vma_list, list) {
		printk("debug_memspace vma start=%lx, end=%lx\n", v->start, v->end);
	}
	printk("\n\n\ndebug_memspace end ====\n");
}

int destroy_process_memspace(struct process_desc *proc)
{
	int ret;
	if (!proc)
		return -EINVAL;

	ret = destroy_mem_desc(proc);
	if (ret)
		return ret;
	return 0;
}

void flush_process_memspace(struct process_desc *proc)
{
	BUG_ON(!proc || !proc->mem);
	mmu_set_tlb(&proc->mem->mem_arch.mmu);
}

void flush_current_memspace(void)
{
	return flush_process_memspace(current_proc_info());
}

/**
 * 配置mmu_walk_info
 */
static int vmem_fault_set_mmu_walk_info(struct mmu_walk_info *info,
	struct vma_desc *v, virt_addr_t addr)
{
	if (!info || !v || !addr)
		return -EINVAL;

	info->in_mmu = &v->at_mem->mem_arch.mmu;
	info->in_faddr = addr;
	return mmu_set_info_prot(info, v->acces);
}

static int vmem_get_file_pos(struct vma_desc *v, virt_addr_t faddr, loff_t *out_pos, size_t* out_size)
{
	virt_addr_t  vs_faddr_sz, realpos, p_fileend = 0;
	if (!v || !faddr || !out_pos || !out_size)
		return -EINVAL;

	vs_faddr_sz = (faddr & PAGE_MASK) - (v->start & PAGE_MASK);
	realpos = (v->offset & PAGE_MASK) + vs_faddr_sz;
	
	if (v->rf_in_v_size) {
		p_fileend = v->rf_in_v_off + v->rf_in_v_size - 1;

		BUG_ON(realpos == p_fileend);
		if (realpos < p_fileend) {
			if ((p_fileend - realpos + 1) >= PAGE_SIZE) {
				*out_size = PAGE_SIZE;
			} else {
				*out_size = p_fileend - realpos + 1;
			}
			*out_pos = realpos;
		}

		if (realpos > p_fileend) {
			*out_size = 0;
			*out_pos = realpos;
		}
	} else if ((v->rf_in_v_size) == 0 && 
			((long)(v->rf_in_v_off) == VMA_OFF_FILE_OUTSIDE)) {
		/**
		 * VMA_OFF_FILE_OUTSIDE表示该VMA区间落在真实文件数据之外
		 * 所以不能读取文件内容，而是应该分配一个为0的页面
		 */
		*out_size = 0;
		*out_pos = realpos;
	} else {
		*out_size = PAGE_SIZE;
		*out_pos = realpos;	
	}

	return 0;
}

/**
 * 检查当前访问方式与vma的权限
 */
static int vmem_mmu_vma_permission(struct vma_desc *v, virt_addr_t addr, unsigned long data)
{
	return arch_mmu_vma_permission(v, addr, data);
}

static int vmem_fault_copy_file_page(struct vma_desc *v, struct mmu_walk_info *info)
{
	struct file *fp;
	loff_t pos;
	loff_t setoff = 0;
	size_t readsz = 0;
	int err, off;
	ssize_t sz;

	fp = (struct file *)v->file;
	if (!fp)
		return -EINVAL;

	err = mmu_kernel_rw_map(info);
	if (err)
		return -EFAULT;

	memset((char *)(info->in_faddr & PAGE_MASK), 0, PAGE_SIZE);
	if (v->flags & VAF_SHARED_MAP) {
		add_to_page_cache(phys_addr_to_page(info->in_paddr), v->file->cache_space,
			((info->in_faddr - v->start) >> PAGE_SHIFT) + (v->offset >> PAGE_SHIFT), PAF_KERNEL);
		return 0;
	}

	BUG_ON(vmem_get_file_pos(v, info->in_faddr, &setoff, &readsz));
	if (readsz) {
		off = filp_llseek(fp, 0, (unsigned long)setoff, &pos, SEEK_SET);
		if (off)
			return -EFAULT;
	
		sz = filp_read(fp, (char *)(info->in_faddr & PAGE_MASK), readsz);
		if (sz < 0) {
			BUG();
			return -EFAULT;
		}
	}

	return 0;
}


static int vmem_fault_cow_new_page(struct vma_desc *v, struct mmu_walk_info *info)
{
	int err;
	virt_addr_t p_addr = 0;
	virt_addr_t old_virt_addr;
	phys_addr_t old_phys_addr;
	if (!v || !info)
		return -EINVAL;
	/**
	 * 目前物理页其实还是内核空间的,
	 * 所以直接通过内核虚拟地址空间来拷贝内存也暂时可行。
	 */
	old_phys_addr = mmu_walk_info_l4_phyadr(info);
	old_virt_addr = (virt_addr_t)linear_phys_to_virt(old_phys_addr);
	/**
	 * 其实这里应该分配用户态的物理页面
	 */
	p_addr = (virt_addr_t)get_one_user_page();
	if (!p_addr)
		return -ENOMEM;
	if (p_addr & (PAGE_SIZE - 1))
		return -EINVAL;
	info->in_paddr = p_addr;

	err = mmu_kernel_rw_map(info);
	if (err) {
		put_one_user_page(p_addr);
		return -EFAULT;
	}

	memcpy((void *)(info->in_faddr & PAGE_MASK), (void *)old_virt_addr, PAGE_SIZE);
	/**
	 * 拷贝结束需要释放旧物理地址,
	 * 这里不需要担心重复释放,因为有引用计数保护它。
	 */
	put_one_user_page(old_phys_addr);
	return mmu_complete_map(info);
}

static int vmem_fault_file_new_page(struct vma_desc *v, struct mmu_walk_info *info)
{
	virt_addr_t p_addr = 0;
	int ret;

	if (!v || !info)
		return -EINVAL;

	p_addr = (virt_addr_t)get_one_user_page();

	if (!p_addr)
		return -ENOMEM;
	if (p_addr & (PAGE_SIZE - 1))
		return -EINVAL;
	info->in_paddr = p_addr;

	/* pr_info("task:%s vmem_fault_file_new_page faddr:%lx , user_addr:%lx [%s]\n",
	 *		current->name, info->in_faddr, info->in_paddr, get_vma_type_string(v));
	 */
	ret = vmem_fault_copy_file_page(v, info);
	if (ret) {
		put_one_user_page(p_addr);
		return ret;
	}

	return mmu_complete_map(info);
}

/**
 * 处理文件映射下的内存访问失败
 */
static int vmem_fault_vma_file(struct vma_desc *v, virt_addr_t addr, unsigned long data, void *ext)
{
	struct mmu_walk_info info;
	struct page_frame *page;
	int ret;

	memset(&info, 0, sizeof(info));
	/**
	 * 对比当前访问方式和vma的权限
	 */
	if (vmem_mmu_vma_permission(v, addr, data))
		return -EFAULT;

	vmem_fault_set_mmu_walk_info(&info, v, addr);

	ret = mmu_ttbl_fault(&info);
	if (ret != MMU_MAP_L3_TBL)
		return ret;

	if (v->flags & VAF_SHARED_MAP) {
		page = pgcache_find_page(v->file->cache_space, ((addr - v->start) >> PAGE_SHIFT) + (v->offset >> PAGE_SHIFT));
		if (page) {
			info.in_paddr = page_to_phys_addr(page);
			return mmu_complete_map(&info);
		}
	}

	ret = mmu_ttbl_permission(&info);
	if (ret == MMU_L4_PERM)
		return vmem_fault_cow_new_page(v, &info);
	if (ret == 0)
		return 0;
	ret = vmem_fault_file_new_page(v, &info);
	/* printk("vmem_fault_file_new_page ret : %d\n", ret); */
	return ret;
}

static int vmem_fault_anonymous_new_page(struct vma_desc *v, struct mmu_walk_info *info)
{
	virt_addr_t p_addr = 0;
	int err;
	if (!v || !info)
		return -EINVAL;
	/**
	 * 其实这里应该分配用户态的物理页面
	 */
	p_addr = (virt_addr_t)get_one_user_page();

	if (!p_addr)
		return -ENOMEM;
	if (p_addr & (PAGE_SIZE - 1))
		return -EINVAL;
	info->in_paddr = p_addr;

	err = mmu_kernel_rw_map(info);
	if (err) {
		put_one_user_page(p_addr);
		return -EFAULT;
	}

	memset((char *)(info->in_faddr & PAGE_MASK), 0, PAGE_SIZE);
	/* pr_info("task:%s vmem_fault_anonymous_new_page faddr:%lx user_addr:%lx [%s]\n",
	 *		current->name, info->in_faddr, info->in_paddr, get_vma_type_string(v));
	 */
	return mmu_complete_map(info);
}

/**
 * 为何要有这个函数，为何要开这个口子
 * 因为有一种可能：在分配堆空间后，用户又调用mmap映射
 * 而映射开始地址传递为NULL，让内核自己选择，这很有可
 * 能在表示堆vma的其后，创建一个相邻的vma，而这导致堆
 * 无法向后扩展，致使应用程序运行失败。目前的解决方案是
 * 开始建立一个空间很大的vma，然后借助于vma的heapend
 * 表示堆的结束地址，让它在vma-start与vma-end之间游
 * 动，从而实现堆中页面映射和反映射，最终达到控制的目的
 * 而这些，首先要在处理匿名映射下的内存访问失败的函数中
 * 对堆的vma进行特殊检查。由于heapend和offset是联合
 * 体，而vma的offset字段是作用于文件映射的，但是堆是
 * 属于匿名映射，故而可以利用起来。
 */
static int vmem_fault_vma_anonymous_check_heap(struct vma_desc *v, virt_addr_t addr,
	unsigned long data, void *ext)
{
	/**
	 * 如果不是堆直接返回0
	 */
	if (!vma_is_heap(v))
		return 0;
	/**
	 * 这里要对比offset，它相当于heap的游标，表示堆的分配大小
	 * 当访问的地址大于offset时，说明访问了未分配的地址
	 */
	if (addr > v->heapend)
		return -EFAULT;
	if (v->heapend > v->end ||
			v->heapend < v->start)
		return -EFAULT;

	return 0;
}

/**
 * 处理匿名映射下的内存访问失败
 */
static int vmem_fault_vma_anonymous(struct vma_desc *v, virt_addr_t addr,
	unsigned long data, void *ext)
{
	struct mmu_walk_info info;
	int ret;
	/**
	 * 对堆的vma_desc要做特殊检查
	 */
	ret = vmem_fault_vma_anonymous_check_heap(v,
								addr, data, ext);
	if (ret)
		return ret;
	/**
	 * 对比当前访问方式和vma的权限
	 */
	ret = vmem_mmu_vma_permission(v, addr, data);
	if (ret)
		return ret;
	vmem_fault_set_mmu_walk_info(&info, v, addr);
	ret = mmu_ttbl_fault(&info);
	if (ret != MMU_MAP_L3_TBL)
		return ret;
	ret = mmu_ttbl_permission(&info);
	if (ret == MMU_L4_PERM)
		return vmem_fault_cow_new_page(v, &info);

	if (ret == 0)
		return 0;
	ret = vmem_fault_anonymous_new_page(v, &info);
	return ret;
}

/**
 * 处理内存访问失败
 */
static int vmem_fault_vma(struct vma_desc *v, virt_addr_t addr, unsigned long data, void *ext)
{
	/**
	 * 不允许既是匿名映射又是文件映射
	 */
	if ((v->flags & VAF_ANONYMOUS_MAP) && (v->flags & VAF_FILE_MAP))
		return -EFAULT;
	if (v->flags & VAF_ANONYMOUS_MAP)
		return vmem_fault_vma_anonymous(v, addr, data, ext);

	if (v->flags & VAF_FILE_MAP)
		return vmem_fault_vma_file(v, addr, data, ext);

	return -EFAULT;
}

/**
 * 不加锁！！虚拟内存访问失败的处理的核心实现
 */
static int vmem_fault_core_nolock(struct mem_desc *m, virt_addr_t addr, 
									unsigned long data, void *ext)
{
	struct vma_iterator viter;
	virt_addr_t start, end;
	start = addr & PAGE_MASK;
	end = (start + PAGE_SIZE) - 1;

	vma_iterator_init(&viter, m, start, end);
	if (find_vma_iterator(&viter, FVFLAG_FAULT))
		return -EFAULT;

	if (viter.vposstate != FVSTATE_ADDR_IN_VMA || 
							viter.vpos == NULL)
		return -EFAULT;

	return vmem_fault_vma(viter.vpos, addr, data, ext);
}

/**
 * 虚拟内存访问失败的处理的核心实现
 */
static int vmem_fault_core(struct mem_desc *m, virt_addr_t addr, unsigned long data, void *ext)
{
	int ret;
	
	down_write(&m->rwsem);
	ret = vmem_fault_core_nolock(m, addr, data, ext);
	up_write(&m->rwsem);
	return ret;
}

/**
 * 查找属于m中的addr的vma
 */
struct vma_desc* vmem_find_vma_nolock(struct mem_desc *m, virt_addr_t addr)
{
	struct vma_iterator viter;
	virt_addr_t start, end;

	start = addr & PAGE_MASK;
	end = (start + PAGE_SIZE) - 1;

	vma_iterator_init(&viter, m, start, end);
	if (find_vma_iterator(&viter, FVFLAG_FAULT)) {
		return NULL;
	}

	if (viter.vposstate != FVSTATE_ADDR_IN_VMA || 
							viter.vpos == NULL) {
		return NULL;
	}

	return viter.vpos;
}

/**
 * 查找属于m中的addr的vma
 */
struct vma_desc* vmem_find_vma(struct mem_desc *m, virt_addr_t addr)
{
	struct vma_desc *v = NULL;
	
	
	down_write(&m->rwsem);
	v = vmem_find_vma_nolock(m, addr);
	up_write(&m->rwsem);
	return v;
}

/**
 * 虚拟内存访问失败的处理接口
 */
int vmem_fault(struct mem_desc *m, virt_addr_t addr, unsigned long data, void *ext)
{
	if (!m || !addr || addr >= USER_VA_END)
		return -EINVAL;

	return vmem_fault_core(m, addr, data, ext);
}

long vmem_brk(unsigned long addr)
{
	struct mem_desc *m = current_mem;
	struct vma_desc *v;
	virt_addr_t t_addr = (virt_addr_t)addr;
	virt_addr_t old_brk;

	if (!m)
		return -EINVAL;

	v = m->vma_heap;
	if (!v)
		return -EINVAL;

	old_brk = v->heapend;


	if (!t_addr)
		return (long)old_brk;
	if (t_addr < v->start)
		return -EINVAL;

	if (t_addr > old_brk)
		return (long)vmem_heap_extension(m, v, t_addr - old_brk, VMA_EXT_UP);

	if (t_addr < old_brk)
		return (long)vmem_heap_extension(m, v, old_brk - t_addr, VMA_EXT_DN);
	return -EFAULT;
}

/**
 * 基于现有vma向上扩大当前vma的大小
 */
static void *mremap_vma_extend(struct mem_desc *m, struct vma_desc *v, virt_addr_t new_end)
{
	struct vma_desc *nextv;

	nextv = vma_next(v, m);

	if (!nextv) {
		if (new_end < USER_ALLOC_END) {
			v->end = new_end;
			return (void *)v->start;
		}
		return NULL;
	}

	if (new_end > v->end && new_end < nextv->start) {
		v->end = new_end;
		return (void *)v->start;
	}
	return NULL;
}

/**
 * 基于现有vma向下缩小当前vma的大小
 */
static void *mremap_vma_shink(struct mem_desc *m, struct vma_desc *v, virt_addr_t new_end)
{
	virt_addr_t end = v->end;
	virt_addr_t unmap_start;
	virt_size_t unmap_size;
	if (new_end > v->start && new_end < v->end) {
		unmap_start = new_end + 1;
		unmap_size = end - new_end;
		/**
		 * 反映射已经缩小的空间
		 */
		if (unsafe_destroy_vma_core(m, unmap_start, (unmap_start + unmap_size - 1)))
			return NULL;
		return (void *)v->start;
	}
	return NULL;
}

/**
 * 为重新映射建立新的虚拟地址区间vma
 */
static struct vma_desc *mremap_vma_new(struct mem_desc *m, struct vma_desc *srcv,
	virt_addr_t new_addr, virt_addr_t new_end, int automap)
{
	struct vma_desc *v, *vpos = NULL;
	struct vma_desc *retv = NULL;
	struct vma_iterator viter;
	void *ret = NULL;
	int state, afind = 0;

	vma_iterator_init(&viter, m, new_addr, new_end);
	
	if (find_vma_iterator(&viter, FVFLAG_MAP)) {
		if (!automap) {
			ret = NULL;
			goto out;
		}
		/**
		 * 重新以map方式查找
		 */
		vma_iterator_init(&viter, m, new_addr, new_end);
	
		if (find_vma_iterator(&viter, FVFLAG_AUTOMAP)) {
			ret = NULL;
			goto out;
		}
		afind = 1;
	}

	if (afind) {
		vpos = viter.vpos;
		state = viter.vposstate;
	} else {
		vpos = viter.fisrt;
		state = viter.fiststate;
	}

	/**
	 * 分配新的vma
	 */
	v = alloced_vma_desc();
	if (!v) {
		retv = NULL;
		goto out;
	}

	/**
	 * 设置vma
	 */
	ret = set_new_vma_desc(m, v, vpos, state, new_addr, new_end, srcv->acces, srcv->flags,
		srcv->file, srcv->offset);
	if (!ret)
		goto free_vma;

	/**
	 * 插入vma
	 */
	ret = insert_vma_desc(m, &retv, vpos, v, state);
	if (ret) {
		set_vma_cache(m, v);
		goto out;
	}

free_vma:
	retv = NULL;
	free_vma_desc(v);
out:
	return retv;
}

/**
 * 将源虚拟地址区间vma的内容复制到目的vma
 * 其实并非直接复制，而是使用映射方式
 */
static int mremap_vma_copy(struct mem_desc *m, struct vma_desc *srcv, struct vma_desc *dstv)
{
	virt_size_t isz, size, srcsize, dstsize;
	virt_addr_t start, to;
	struct mmu_walk_info sinfo, dinfo;

	memset(&sinfo, 0, sizeof(sinfo));
	memset(&dinfo, 0, sizeof(dinfo));

	srcsize = srcv->end - srcv->start + 1;
	dstsize = dstv->end - dstv->start + 1;

	if (srcsize < dstsize) {
		start = srcv->start;
		size = srcsize;
	} else {
		start = srcv->start;
		size = dstsize;
	}

	to = dstv->start;
	vmem_fault_set_mmu_walk_info(&sinfo, srcv, start);
	vmem_fault_set_mmu_walk_info(&dinfo, dstv, to);

	for (isz = 0; isz < size; isz += PAGE_SIZE) {
		sinfo.in_faddr = start + isz;
		dinfo.in_faddr = to + isz;
		/**
		 * 查找源虚拟地址有没有映射对应的物理页面
		 */
		if (mmu_find_ttbl(&sinfo))
			continue;
		/**
		 * 断开源虚拟地址映射的物理页面
		 */
		if (mmu_cutoff_vaddr(&sinfo))
			return -EFAULT;
		/**
		 * 将源虚拟地址对应的物理页面设备为目的虚拟地址的mmu_walk中
		 */
		dinfo.in_paddr = ((phys_addr_t)sinfo.out_l4) & PAGE_MASK;
		/**
		 * 接通目的虚拟地址的物理页面
		 */
		if (mmu_connect_vaddr(&dinfo))
			return -EFAULT;
	}
	return 0;
}

/**
 * 移动已有的虚拟地址区间vma
 */
static void *mremap_vma_move(struct mem_desc *m, struct vma_desc *v, virt_addr_t new_addr,
	virt_addr_t new_end, int automap, int dontunmap)
{
	struct vma_desc *ret;

	ret = mremap_vma_new(m, v, new_addr, new_end, automap);
	if (!ret)
		return NULL;

	if (mremap_vma_copy(m, v, ret))
		if (unsafe_destroy_vma_core(m, ret->start, ret->end))
			return NULL;
	
	if (!dontunmap) {
		if (unsafe_destroy_vma_core(m, v->start, v->end)) {
			if (unsafe_destroy_vma_core(m, ret->start, ret->end))
				return NULL;
			return NULL;
		}
	}
	
	return (void *)ret->start;
}

/**
 * 基于已有的虚拟地址区间vma
 * 扩大、缩小、移动到固定的地址空间
 */
static void *mremap_vma_fixed(struct mem_desc *m, struct vma_desc *v, 
					virt_addr_t addr, virt_addr_t end, 
					virt_addr_t new_addr, virt_addr_t new_end, 
					unsigned long flags)
{
	if ((new_end - new_addr + 1) > TASK_SIZE ||
		 new_addr > (TASK_SIZE - (new_end - new_addr + 1)))
		return NULL;

	/* 新旧地址不能重叠 */
	if (flags & MREMAP_FIXED)
		if (end > new_addr && new_end > addr)
			return NULL;
	
	if (flags & MREMAP_FIXED) {
		if (!new_addr)
			return NULL;

		if (unsafe_destroy_vma_core(m, new_addr, new_end))
			return NULL;
	}
	return mremap_vma_move(m, v, new_addr, new_end, 
			!(flags & MREMAP_FIXED), (flags & MREMAP_DONTUNMAP));
}

static void *mremap_vma_maymove(struct mem_desc *m, struct vma_desc *v, 
					virt_addr_t addr, virt_addr_t end, 
					virt_addr_t new_addr, virt_addr_t new_end, 
					unsigned long flags)
{
	virt_addr_t vend = v->end;
	virt_size_t new_size = new_end - new_addr + 1;
	virt_addr_t se_end;
	if (!new_addr) {
		se_end = v->start + new_size - 1;
		if (se_end < vend)
			return mremap_vma_shink(m, v, se_end);
		if (se_end > vend)
			return mremap_vma_extend(m, v, se_end);
		if (se_end == vend)
			return (void *)v->start;
	} else if (new_addr)
		return mremap_vma_move(m, v, new_addr, new_end, 1, 0);
	return NULL;
}

/**
 * 对已有的虚拟地址区间重新映射
 * 核心实现
 */
static void *vmem_mremap_core(virt_addr_t addr, virt_addr_t end,
					virt_addr_t new_addr, virt_addr_t new_end,
					unsigned long flags)
{
	struct mem_desc *m = current_mem;
	struct vma_desc *v = NULL;
	struct vma_iterator viter;
	void *ret = NULL;

	down_write(&m->rwsem);
	
	vma_iterator_init(&viter, m, addr, end);
	
	if (find_vma_iterator(&viter, FVFLAG_REMAP)) {
		ret = NULL;
		goto out;
	}

	v = viter.vpos;
	if (addr < v->start || end > v->end) {
		ret = NULL;
		goto out;
	}
	
	if (flags & (MREMAP_FIXED | MREMAP_DONTUNMAP)) {
		ret = mremap_vma_fixed(m, v, addr, end, new_addr, new_end, flags);
		goto out;
	}


	ret = mremap_vma_maymove(m, v, addr, end, new_addr, new_end, flags);
out:
	up_write(&m->rwsem);
	return ret;
}

/**
 * 对已有的虚拟地址区间重新映射
 * 扩大、缩小、移动
 */
unsigned long vmem_mremap(virt_addr_t addr, virt_size_t size,
					virt_addr_t new_addr, virt_size_t new_size,
					unsigned long flags)
{
	virt_size_t tsize, tnew_size;
	virt_addr_t end, new_end;
	unsigned long ret = 0;

	if (!addr || !size)
		return ret;

	if (!new_size)
		return ret;

	if (flags & ~(MREMAP_FIXED | MREMAP_MAYMOVE | MREMAP_DONTUNMAP))
		return ret;

	if (flags & MREMAP_FIXED && !(flags & MREMAP_MAYMOVE))
		return ret;

	if (flags & MREMAP_DONTUNMAP &&
			(!(flags & MREMAP_MAYMOVE) || size != new_size))
		return ret;

	if (addr & ~PAGE_MASK || new_addr & ~PAGE_MASK)
		return ret;

	tsize = PAGE_ALIGN(size);
	tnew_size = PAGE_ALIGN(new_size);

	/**
	 * 注意溢出
	 */
	if (!uadd_is_ok(addr, tsize))
		return 0;
	if (!uadd_is_ok(addr, tnew_size))
		return 0;
	if (!uadd_is_ok(new_addr, tnew_size))
		return 0;

	end = addr + tsize - 1;
	new_end = new_addr + tnew_size - 1;

	return (unsigned long)vmem_mremap_core(addr, end, new_addr, new_end, flags);
}


/**
 * 修改vma区间对应的页面的属性
 */
static int vmem_mprotect_vma_pages(struct mem_desc *m, struct vma_desc *v,
									virt_addr_t start,
									virt_addr_t end,
									unsigned long prot)
{
	struct mmu_walk_info info;
	if (!m || !v || !start || !end)
		return -EINVAL;
	if (start < v->start || end > v->end)
		return -EINVAL;
	memset(&info, 0, sizeof(info));

	info.in_mmu = &m->mem_arch.mmu;
	info.in_mprotstart = start;
	info.in_mprotend = end;

	mmu_set_info_prot(&info, v->acces);
	
	if (mmu_mprotect_range(&info))
		return -EFAULT;
	return 0;
}

static int direct_mprotect_vma(struct mem_desc *m, struct vma_desc *v,
								virt_addr_t start, virt_addr_t end,
								unsigned long prot)
{
	if (!m || !v)
		return -EINVAL;
	if (v->start != start || v->end != end)
		return -EINVAL;

	if (vma_compare_prot(v, prot))
		return 0;

	if (vmem_mprotect_vma_pages(m, v, v->start, v->end, prot))
		return -EFAULT;

	vma_reset_acces_prot(v, prot);
	return 0;
}

int vma_handle_realfile_offset(struct vma_desc* p, virt_addr_t orig_rfoff, virt_size_t orig_rfsz)
{
	virt_size_t vsize = 0;
	virt_addr_t orig_rfend = orig_rfoff + orig_rfsz - 1;
	virt_addr_t vfoff;
	virt_addr_t vfend;
	int ret = 0;
	if (!p) {
		return -EINVAL;
	}
	if (!p->file)
		return 0;
	if (!orig_rfsz)
		return 0;
	
	vsize = p->end - p->start + 1;
	vfoff = p->offset;
	vfend = vfoff + vsize - 1;

	if (vfoff <= orig_rfoff && orig_rfend <= vfend) {
		return 0;
	}

	if (vfoff <= orig_rfoff && orig_rfoff < vfend && vfend < orig_rfend) {
		p->rf_in_v_off = orig_rfoff;
		p->rf_in_v_size = vfend - p->rf_in_v_off + 1;
		ret = 1;
	}

	if (vfoff >= orig_rfoff && vfoff < orig_rfend && vfend >= orig_rfend) {
		p->rf_in_v_off = p->offset;
		p->rf_in_v_size = orig_rfend - p->rf_in_v_off + 1;
		BUG_ON(ret == 1);
		ret = 2;
	}

	if (vfoff > orig_rfoff && vfend < orig_rfend) {
		p->rf_in_v_off = p->offset;
		p->rf_in_v_size = vsize;
		BUG_ON(ret == 1 || ret == 2);
		ret = 3;
	}

	if (vfoff >= orig_rfend && vfend > orig_rfend) {
		/**
		 * VMA_OFF_FILE_OUTSIDE表示该VMA区间落在真实文件数据之外
		 * 用于vmem_get_file_pos函数中做为判断依据
		 */
		p->rf_in_v_off = (off_t)VMA_OFF_FILE_OUTSIDE;
		p->rf_in_v_size = 0;
		BUG_ON(ret == 1 || ret == 2 || ret == 3);
		ret = 4;
	}
	
	if (vfoff < orig_rfoff && vfend <= orig_rfoff) {
		/**
		 * VMA_OFF_FILE_OUTSIDE表示该VMA区间落在真实文件数据之外
		 * 用于vmem_get_file_pos函数中做为判断依据
		 */
		p->rf_in_v_off = (off_t)VMA_OFF_FILE_OUTSIDE;
		p->rf_in_v_size = 0;
		BUG_ON(ret == 1 || ret == 2 || ret == 3 || ret == 4);
		ret = 5;
	}
	BUG_ON(!ret);
	return 0;
}

static int mprotect_vma_prev(struct mem_desc *m, struct vma_desc *v,
								virt_addr_t start, virt_addr_t end,
								unsigned long prot)
{
	struct vma_desc *pvma, *out;
	virt_addr_t orig_rfoff = 0;
	virt_size_t orig_rfsz = 0;

	pvma = alloced_vma_desc();
	if (!pvma)
		return -ENOMEM;

	if (vmem_mprotect_vma_pages(m, v, start, end, prot)) {
		free_vma_desc(pvma);
		return -EFAULT;
	}

	memcpy((void *)pvma, (const void *)v, sizeof(*pvma));

	list_init(&pvma->list);
	RB_NODE_INIT(&pvma->rbnode);
	smp_lock_init(&pvma->lock);

	pvma->start = start;
	pvma->end = end;

	v->start = end + 1;
	/**
	 * 处理文件偏移
	 */
	if (v->file) {
		v->offset = v->offset + (pvma->end + 1 - start);
		orig_rfoff = v->rf_in_v_off;
		orig_rfsz = v->rf_in_v_size;
		if (orig_rfsz) {
			BUG_ON(vma_handle_realfile_offset(pvma, orig_rfoff, orig_rfsz));
			BUG_ON(vma_handle_realfile_offset(v, orig_rfoff, orig_rfsz));
		}
	}
	vma_reset_acces_prot(pvma, prot);
	BUG_ON(!insert_vma_desc(m, &out, v, pvma, FVSTATE_ON_PREV));
	return 0;
}

static int mprotect_vma_next(struct mem_desc *m, struct vma_desc *v,
								virt_addr_t start, virt_addr_t end,
								unsigned long prot)
{
	struct vma_desc *nvma, *out;
	virt_addr_t orig_rfoff = 0;
	virt_size_t orig_rfsz = 0;
	nvma = alloced_vma_desc();
	if (!nvma)
		return -ENOMEM;

	if (vmem_mprotect_vma_pages(m, v, start, end, prot)) {
		free_vma_desc(nvma);
		return -EFAULT;
	}

	memcpy((void *)nvma, (const void *)v, sizeof(*nvma));

	list_init(&nvma->list);
	RB_NODE_INIT(&nvma->rbnode);
	smp_lock_init(&nvma->lock);

	nvma->start = start;
	nvma->end = end;

	v->end = start - 1;
	/**
	 * 处理文件偏移
	 */
	if (nvma->file) {
		nvma->offset = v->offset + (v->end + 1 - v->start);
		orig_rfoff = v->rf_in_v_off;
		orig_rfsz = v->rf_in_v_size;
		if (orig_rfsz) {
			BUG_ON(vma_handle_realfile_offset(v, orig_rfoff, orig_rfsz));
			BUG_ON(vma_handle_realfile_offset(nvma, orig_rfoff, orig_rfsz));
		}
	}
	vma_reset_acces_prot(nvma, prot);
	BUG_ON(!insert_vma_desc(m, &out, v, nvma, FVSTATE_ON_NEXT));
	return 0;
}

static int mprotect_vma_middle(struct mem_desc *m, struct vma_desc *v,
								virt_addr_t start, virt_addr_t end,
								unsigned long prot)
{
	struct vma_desc *nvma, *mvma, *out;
	virt_addr_t tmpend;

	virt_addr_t orig_rfoff = 0;
	virt_size_t orig_rfsz = 0;

	nvma = alloced_vma_desc();
	if (!nvma)
		return -ENOMEM;
	mvma = alloced_vma_desc();
	if (!mvma) {
		free_vma_desc(nvma);
		return -ENOMEM;
	}

	if (vmem_mprotect_vma_pages(m, v, start, end, prot)) {
		free_vma_desc(mvma);
		free_vma_desc(nvma);
		return -EFAULT;
	}

	memcpy((void *)mvma, (const void *)v, sizeof(*mvma));
	memcpy((void *)nvma, (const void *)v, sizeof(*nvma));

	list_init(&mvma->list);
	RB_NODE_INIT(&mvma->rbnode);
	smp_lock_init(&mvma->lock);

	list_init(&nvma->list);
	RB_NODE_INIT(&nvma->rbnode);
	smp_lock_init(&nvma->lock);

	tmpend = v->end;
	v->end = start - 1;

	mvma->start = start;
	mvma->end = end;

	nvma->start = end + 1;
	nvma->end = tmpend;

	/**
	 * 处理文件偏移
	 */
	if (mvma->file) {
		mvma->offset = v->offset + (v->end + 1 - v->start);
		nvma->offset = v->offset + (mvma->end + 1 - v->start);

		orig_rfoff = v->rf_in_v_off;
		orig_rfsz = v->rf_in_v_size;
		if (orig_rfsz) {
			BUG_ON(vma_handle_realfile_offset(v, orig_rfoff, orig_rfsz));
			BUG_ON(vma_handle_realfile_offset(mvma, orig_rfoff, orig_rfsz));
			BUG_ON(vma_handle_realfile_offset(nvma, orig_rfoff, orig_rfsz));
		}
	}

	vma_reset_acces_prot(mvma, prot);
	BUG_ON(!insert_vma_desc(m, &out, v, mvma, FVSTATE_ON_NEXT));
	BUG_ON(!insert_vma_desc(m, &out, mvma, nvma, FVSTATE_ON_NEXT));
	return 0;
}

static int modify_mprotect_vma(struct mem_desc *m, struct vma_desc *v,
								virt_addr_t start, virt_addr_t end,
								unsigned long prot)
{
	if (!m || !v)
		return -EINVAL;

	if (v->start > start || v->end < end)
		return -EINVAL;

	if (vma_compare_prot(v, prot))
		return 0;

	if (v->start == start && end < v->end)
		return mprotect_vma_prev(m, v, start, end, prot);

	if (v->start < start && v->end == end)
		return mprotect_vma_next(m, v, start, end, prot);

	if (v->start < start && v->end > end)
		return mprotect_vma_middle(m, v, start, end, prot);

	return -EFAULT;
}

static int mproted_onevma_vmaiterator(struct vma_iterator* viter, struct vma_desc* vma, unsigned long prot)
{
	if (!viter || !vma)
		return -EINVAL;
	if (vma->start < viter->start && 
			viter->start < vma->end && viter->end >= vma->end) {
		return modify_mprotect_vma(viter->m, vma, viter->start, vma->end, prot);
	}

	if (vma->start < viter->end && 
			viter->end < vma->end && viter->start <= vma->start) {
		return modify_mprotect_vma(viter->m, vma, vma->start, viter->end, prot);
	}

	if (vma->start < viter->start && viter->end < vma->end) {
		return modify_mprotect_vma(viter->m, vma, viter->start, viter->end, prot);
	}
	
	if (vma->start >= viter->start && viter->end >= vma->end) {
		return direct_mprotect_vma(viter->m, vma, vma->start, vma->end, prot);
	}

	return -EFAULT;
}

static int mproted_vmas_range_vmaiterator(struct vma_iterator* viter, unsigned long prot)
{
	struct vma_desc* v, *n;
	if (!viter || !viter->m)
		return -EINVAL;
	if (fixed_addrspace_is_free(viter))
		return 0;

	if (viter->fisrt == viter->last) {
		BUG_ON(mproted_onevma_vmaiterator(viter, viter->fisrt, prot));
		return 0;
	}

	BUG_ON(viter->fiststate != FVSTATE_ADDR_IN_VMA && viter->fiststate != FVSTATE_ON_PREV);
	BUG_ON(viter->laststate != FVSTATE_ADDR_IN_VMA && viter->laststate != FVSTATE_ON_PREV);

	for (v = viter->fisrt; v->start < viter->end; ) {
		n = vma_next(v, viter->m);

		BUG_ON(mproted_onevma_vmaiterator(viter, v, prot));
		if (n)
			v = n;
		else
		 	break;
	}

	return 0;
}

static int vmem_mprotect_core(virt_addr_t addr, virt_addr_t end, unsigned long prot)
{
	struct mem_desc *m = current_mem;
	virt_addr_t new_addr = addr;
	struct vma_iterator viter;
	int ret = -EFAULT;

	/**
	 * 这样的加锁非常粗暴，以后优化
	 */
	down_write(&m->rwsem);
	
	/**
	 * 根据虚拟地址查找vma
	 */
	vma_iterator_init(&viter, m, new_addr, end);
	if (find_vma_iterator(&viter, FVFLAG_MPROTECT)) {
		ret = -EINVAL;
		goto unlock;
	}

	ret = mproted_vmas_range_vmaiterator(&viter, prot);

unlock:
	up_write(&m->rwsem);
	return ret;
}

int vmem_mprotect(virt_addr_t addr, virt_size_t len, unsigned long prot)
{
	virt_addr_t end;

	if (addr & ~PAGE_MASK)
		return -EINVAL;

	len = PAGE_ALIGN(len);
	end = addr + len - 1;
	if (end < addr)
		return -EINVAL;

	if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
		return -EINVAL;

	if (end == addr)
		return 0;

	return vmem_mprotect_core(addr, end, prot);
}

static int vmem_map_range_uaddr_core(virt_addr_t addr, virt_addr_t end, unsigned long prot)
{
	struct mem_desc *m = current_mem;
	struct vma_desc *v = NULL;
	virt_addr_t new_addr = addr;
	struct mmu_walk_info info;
	struct vma_iterator viter;
	int ret = -EFAULT;

	down_write(&m->rwsem);
	/**
	 * 根据虚拟地址查找vma
	 */
	vma_iterator_init(&viter, m, new_addr, end);
	
	if (find_vma_iterator(&viter, FVFLAG_FAULT)) {
		ret = -EFAULT;
		goto unlock;
	}
	if (viter.vposstate != FVSTATE_ADDR_IN_VMA || 
							viter.vpos == NULL) {
		ret = -EFAULT;
		goto unlock;
	}

	v = viter.vpos;
	
	vmem_fault_set_mmu_walk_info(&info, v, new_addr);
	info.in_mapstart = new_addr;
	info.in_mapend = end;

	ret = mmu_map_range(&info);

unlock:
	up_write(&m->rwsem);
	return ret;
}

int vmem_map_range_uaddr(virt_addr_t addr, virt_size_t len, unsigned long prot)
{
	virt_addr_t end;

	if (addr & ~PAGE_MASK)
		return -EINVAL;

	len = PAGE_ALIGN(len);
	end = addr + len - 1;
	if (end < addr)
		return -EINVAL;

	if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
		return -EINVAL;

	if (end == addr)
		return 0;

	return vmem_map_range_uaddr_core(addr, end, prot);
}

/**
 * 清除mem_desc中的所有vma_desc结构
 */
static int exit_mem_vma(struct mem_desc *m)
{
	int ret;
	struct vma_desc *vma, *n;
	if (!m)
		return -EINVAL;
	down_write(&m->rwsem);

	list_for_each_entry_safe(vma, n, &m->vma_list, list) {
		/* pr_info("exit_mem_vma vma start:[%lx] end:[%lx] type:[%s], mm:[%lx]\n",
		 *	vma->start, vma->end, get_vma_type_string(vma), vma->at_mem);
		 */
		ret = direct_destroy_vma(m, vma, vma->start, vma->end);
		if (ret) {
			ret = -EFAULT;
			goto out;
		}

		if (vma == m->vma_stack)
			m->vma_stack = NULL;
		if (vma == m->vma_heap)
			m->vma_heap = NULL;
		if (vma == m->vma_env)
			m->vma_env = NULL;

	}

	ret = 0;
out:
	up_write(&m->rwsem);
	return 0;
}

/**
 * 清除mem_desc中的所有mmu的页表
 */
static int exit_mem_mmu(struct process_desc *proc, struct mem_desc *m)
{
	int ret;
	if (!proc || !m)
		return -EINVAL;

	down_write(&m->rwsem);
	
	ret = mmu_exit(proc, m);
	
	up_write(&m->rwsem);
	return ret;
}

static int destroy_process_mmu(struct process_desc *proc)
{
	struct mem_desc *m;

	if (!proc || !proc->mem)
		return -EINVAL;

	/* 删除用户态页表 */
	m = proc->mem;
	if (accurate_read(&m->count)) 
		BUG();

	BUG_ON(exit_mem_mmu(proc, m));
	return 0;
}

/**
 * 销毁进程的内存描述符
 */
int destroy_mem_desc(struct process_desc *proc)
{
	struct mem_desc *m;
	long conut;
	int ret;
	if (!proc)
		return -EINVAL;
	if (!proc->mem)
		return -ENODATA;

	/**
	 * 减少内存描述符计数器并判断是否大于等于1
	 * 因为内存描述符可能是共享的，其它proc可以指向它
	 */
	conut = mem_desc_put(proc->mem);
	if (conut >= 1) {
		/**
		 * 与proc断开联系
		 */
		m = proc->mem;
		__set_process_mem(proc, NULL);
		if (m->at_proc == proc)
			m->at_proc = NULL;
		return 0;
	}

	ret = destroy_process_vma(proc);
	if (ret)
		return ret;
	ret = destroy_process_mmu(proc);
	if (ret)
		return ret;

	m = proc->mem;
	__set_process_mem(proc, NULL);

	/**
	 * 删除内存描述符释放其占用的内存
	 */
	m->at_proc = NULL;
	free_mem_desc(m);
	return 0;
}

void loosen_mem(struct mem_desc* m)
{
	long conut;
	int ret;

	/**
	 * 减少内存描述符计数器并判断是否大于等于1
	 * 因为内存描述符可能是共享的
	 */
	conut = mem_desc_put(m);
	if (conut >= 1)
		return;

	ret = exit_mem_vma(m);
	BUG_ON(ret);

	ret = exit_mem_mmu(m->at_proc, m);
	BUG_ON(ret);
	m->at_proc = NULL;
	free_mem_desc(m);
}

int exit_mem_desc(struct process_desc *proc)
{
	struct mem_desc *m;
	if (!proc)
		return -EINVAL;
	if (!proc->mem)
		return -ENODATA;

	m = proc->mem;
	__set_process_mem(proc, NULL);
	loosen_mem(m);
	return 0;
}

/**
 * 清除mem_desc中的所有相关数据结构
 */
int exit_mem(struct process_desc *proc, struct mem_desc *m)
{
	// struct task_desc *tsk;

	if (!proc || !m || proc->mem != m)
		return -EINVAL;

	// tsk = proc->task;

	// if (tsk->flags & PF_VFORK) {
	// 	tsk->flags &= ~PF_VFORK;
	// 	up(task_relation_parent(tsk)->vfork_sem);
	// }

	// /**
	//  * 清除子进程的tid，并且用户态置0，唤醒在地址上等待的futex。
	//  */
	// if (tsk->clear_child_tid && accurate_read(&m->count) > 1) {
	// 	u32 __user * tidptr = tsk->clear_child_tid;
	// 	tsk->clear_child_tid = NULL;

	// 	/**
	// 	 * 我们不检查错误代码 - 如果用户空间没有设置正确的指针，
	// 	 * 那就运气不好了。
	// 	 */
	// 	put_user(0, tidptr);
	// 	sys_futex(tidptr, FUTEX_WAKE, 1, NULL, NULL, 0);
	// }

	return exit_mem_desc(proc);
}

/*
 * brk系统调用
 */
long sys_brk(unsigned long brk)
{
	return vmem_brk(brk);
}

long sys_mmap(void *addr, size_t len, unsigned long access, unsigned long flags, int fd, off_t offset)
{
	long ret = -1; 
	if (!len || !flags)
		return -EINVAL;

	ret = (long)vmem_mmap(addr, len, fd, offset, access, flags);

	return ret;
}

long sys_munmap(void *addr, size_t len)
{
	int ret = vmem_munmmap(addr, len);
	WARN_ON(ret, "sys_munmmap_core:%x addr:%p len:%lx\n",
			ret, addr, len);
	return (long)ret;
}


long sys_mremap(unsigned long addr, unsigned long old_len,
		unsigned long new_len, unsigned long flags,	unsigned long new_addr)
{
	unsigned long ret = -EINVAL;
	ret = vmem_mremap(addr, old_len, new_addr, new_len, flags);
	if (!ret)
		return -1;

	return ret;
}

long sys_mprotect(unsigned long start, size_t len, unsigned long prot)
{
	return vmem_mprotect((virt_addr_t)start, (virt_size_t)len, prot);
}
